325f2c0da30aad026ff2c7847db09b5bb4337f32
[platform/framework/web/crosswalk.git] / src / v8 / src / x64 / lithium-x64.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #if V8_TARGET_ARCH_X64
8
9 #include "src/lithium-allocator-inl.h"
10 #include "src/x64/lithium-x64.h"
11 #include "src/x64/lithium-codegen-x64.h"
12 #include "src/hydrogen-osr.h"
13
14 namespace v8 {
15 namespace internal {
16
17 #define DEFINE_COMPILE(type)                            \
18   void L##type::CompileToNative(LCodeGen* generator) {  \
19     generator->Do##type(this);                          \
20   }
21 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
22 #undef DEFINE_COMPILE
23
24
25 #ifdef DEBUG
26 void LInstruction::VerifyCall() {
27   // Call instructions can use only fixed registers as temporaries and
28   // outputs because all registers are blocked by the calling convention.
29   // Inputs operands must use a fixed register or use-at-start policy or
30   // a non-register policy.
31   ASSERT(Output() == NULL ||
32          LUnallocated::cast(Output())->HasFixedPolicy() ||
33          !LUnallocated::cast(Output())->HasRegisterPolicy());
34   for (UseIterator it(this); !it.Done(); it.Advance()) {
35     LUnallocated* operand = LUnallocated::cast(it.Current());
36     ASSERT(operand->HasFixedPolicy() ||
37            operand->IsUsedAtStart());
38   }
39   for (TempIterator it(this); !it.Done(); it.Advance()) {
40     LUnallocated* operand = LUnallocated::cast(it.Current());
41     ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
42   }
43 }
44 #endif
45
46
47 void LInstruction::PrintTo(StringStream* stream) {
48   stream->Add("%s ", this->Mnemonic());
49
50   PrintOutputOperandTo(stream);
51
52   PrintDataTo(stream);
53
54   if (HasEnvironment()) {
55     stream->Add(" ");
56     environment()->PrintTo(stream);
57   }
58
59   if (HasPointerMap()) {
60     stream->Add(" ");
61     pointer_map()->PrintTo(stream);
62   }
63 }
64
65
66 void LInstruction::PrintDataTo(StringStream* stream) {
67   stream->Add("= ");
68   for (int i = 0; i < InputCount(); i++) {
69     if (i > 0) stream->Add(" ");
70     if (InputAt(i) == NULL) {
71       stream->Add("NULL");
72     } else {
73       InputAt(i)->PrintTo(stream);
74     }
75   }
76 }
77
78
79 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
80   if (HasResult()) result()->PrintTo(stream);
81 }
82
83
84 void LLabel::PrintDataTo(StringStream* stream) {
85   LGap::PrintDataTo(stream);
86   LLabel* rep = replacement();
87   if (rep != NULL) {
88     stream->Add(" Dead block replaced with B%d", rep->block_id());
89   }
90 }
91
92
93 bool LGap::IsRedundant() const {
94   for (int i = 0; i < 4; i++) {
95     if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
96       return false;
97     }
98   }
99
100   return true;
101 }
102
103
104 void LGap::PrintDataTo(StringStream* stream) {
105   for (int i = 0; i < 4; i++) {
106     stream->Add("(");
107     if (parallel_moves_[i] != NULL) {
108       parallel_moves_[i]->PrintDataTo(stream);
109     }
110     stream->Add(") ");
111   }
112 }
113
114
115 const char* LArithmeticD::Mnemonic() const {
116   switch (op()) {
117     case Token::ADD: return "add-d";
118     case Token::SUB: return "sub-d";
119     case Token::MUL: return "mul-d";
120     case Token::DIV: return "div-d";
121     case Token::MOD: return "mod-d";
122     default:
123       UNREACHABLE();
124       return NULL;
125   }
126 }
127
128
129 const char* LArithmeticT::Mnemonic() const {
130   switch (op()) {
131     case Token::ADD: return "add-t";
132     case Token::SUB: return "sub-t";
133     case Token::MUL: return "mul-t";
134     case Token::MOD: return "mod-t";
135     case Token::DIV: return "div-t";
136     case Token::BIT_AND: return "bit-and-t";
137     case Token::BIT_OR: return "bit-or-t";
138     case Token::BIT_XOR: return "bit-xor-t";
139     case Token::ROR: return "ror-t";
140     case Token::SHL: return "sal-t";
141     case Token::SAR: return "sar-t";
142     case Token::SHR: return "shr-t";
143     default:
144       UNREACHABLE();
145       return NULL;
146   }
147 }
148
149
150 bool LGoto::HasInterestingComment(LCodeGen* gen) const {
151   return !gen->IsNextEmittedBlock(block_id());
152 }
153
154
155 template<int R>
156 bool LTemplateResultInstruction<R>::MustSignExtendResult(
157     LPlatformChunk* chunk) const {
158   HValue* hvalue = this->hydrogen_value();
159   return hvalue != NULL &&
160       hvalue->representation().IsInteger32() &&
161       chunk->GetDehoistedKeyIds()->Contains(hvalue->id());
162 }
163
164
165 void LGoto::PrintDataTo(StringStream* stream) {
166   stream->Add("B%d", block_id());
167 }
168
169
170 void LBranch::PrintDataTo(StringStream* stream) {
171   stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
172   value()->PrintTo(stream);
173 }
174
175
176 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
177   stream->Add("if ");
178   left()->PrintTo(stream);
179   stream->Add(" %s ", Token::String(op()));
180   right()->PrintTo(stream);
181   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
182 }
183
184
185 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
186   stream->Add("if is_object(");
187   value()->PrintTo(stream);
188   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
189 }
190
191
192 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
193   stream->Add("if is_string(");
194   value()->PrintTo(stream);
195   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
196 }
197
198
199 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
200   stream->Add("if is_smi(");
201   value()->PrintTo(stream);
202   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
203 }
204
205
206 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
207   stream->Add("if is_undetectable(");
208   value()->PrintTo(stream);
209   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
210 }
211
212
213 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
214   stream->Add("if string_compare(");
215   left()->PrintTo(stream);
216   right()->PrintTo(stream);
217   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
218 }
219
220
221 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
222   stream->Add("if has_instance_type(");
223   value()->PrintTo(stream);
224   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
225 }
226
227
228 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
229   stream->Add("if has_cached_array_index(");
230   value()->PrintTo(stream);
231   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
232 }
233
234
235 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
236   stream->Add("if class_of_test(");
237   value()->PrintTo(stream);
238   stream->Add(", \"%o\") then B%d else B%d",
239               *hydrogen()->class_name(),
240               true_block_id(),
241               false_block_id());
242 }
243
244
245 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
246   stream->Add("if typeof ");
247   value()->PrintTo(stream);
248   stream->Add(" == \"%s\" then B%d else B%d",
249               hydrogen()->type_literal()->ToCString().get(),
250               true_block_id(), false_block_id());
251 }
252
253
254 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
255   stream->Add(" = ");
256   function()->PrintTo(stream);
257   stream->Add(".code_entry = ");
258   code_object()->PrintTo(stream);
259 }
260
261
262 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
263   stream->Add(" = ");
264   base_object()->PrintTo(stream);
265   stream->Add(" + ");
266   offset()->PrintTo(stream);
267 }
268
269
270 void LCallJSFunction::PrintDataTo(StringStream* stream) {
271   stream->Add("= ");
272   function()->PrintTo(stream);
273   stream->Add("#%d / ", arity());
274 }
275
276
277 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
278   for (int i = 0; i < InputCount(); i++) {
279     InputAt(i)->PrintTo(stream);
280     stream->Add(" ");
281   }
282   stream->Add("#%d / ", arity());
283 }
284
285
286 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
287   context()->PrintTo(stream);
288   stream->Add("[%d]", slot_index());
289 }
290
291
292 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
293   context()->PrintTo(stream);
294   stream->Add("[%d] <- ", slot_index());
295   value()->PrintTo(stream);
296 }
297
298
299 void LInvokeFunction::PrintDataTo(StringStream* stream) {
300   stream->Add("= ");
301   function()->PrintTo(stream);
302   stream->Add(" #%d / ", arity());
303 }
304
305
306 void LCallNew::PrintDataTo(StringStream* stream) {
307   stream->Add("= ");
308   constructor()->PrintTo(stream);
309   stream->Add(" #%d / ", arity());
310 }
311
312
313 void LCallNewArray::PrintDataTo(StringStream* stream) {
314   stream->Add("= ");
315   constructor()->PrintTo(stream);
316   stream->Add(" #%d / ", arity());
317   ElementsKind kind = hydrogen()->elements_kind();
318   stream->Add(" (%s) ", ElementsKindToString(kind));
319 }
320
321
322 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
323   arguments()->PrintTo(stream);
324
325   stream->Add(" length ");
326   length()->PrintTo(stream);
327
328   stream->Add(" index ");
329   index()->PrintTo(stream);
330 }
331
332
333 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
334   return spill_slot_count_++;
335 }
336
337
338 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
339   // All stack slots are Double stack slots on x64.
340   // Alternatively, at some point, start using half-size
341   // stack slots for int32 values.
342   int index = GetNextSpillIndex(kind);
343   if (kind == DOUBLE_REGISTERS) {
344     return LDoubleStackSlot::Create(index, zone());
345   } else {
346     ASSERT(kind == GENERAL_REGISTERS);
347     return LStackSlot::Create(index, zone());
348   }
349 }
350
351
352 void LStoreNamedField::PrintDataTo(StringStream* stream) {
353   object()->PrintTo(stream);
354   hydrogen()->access().PrintTo(stream);
355   stream->Add(" <- ");
356   value()->PrintTo(stream);
357 }
358
359
360 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
361   object()->PrintTo(stream);
362   stream->Add(".");
363   stream->Add(String::cast(*name())->ToCString().get());
364   stream->Add(" <- ");
365   value()->PrintTo(stream);
366 }
367
368
369 void LLoadKeyed::PrintDataTo(StringStream* stream) {
370   elements()->PrintTo(stream);
371   stream->Add("[");
372   key()->PrintTo(stream);
373   if (hydrogen()->IsDehoisted()) {
374     stream->Add(" + %d]", base_offset());
375   } else {
376     stream->Add("]");
377   }
378 }
379
380
381 void LStoreKeyed::PrintDataTo(StringStream* stream) {
382   elements()->PrintTo(stream);
383   stream->Add("[");
384   key()->PrintTo(stream);
385   if (hydrogen()->IsDehoisted()) {
386     stream->Add(" + %d] <-", base_offset());
387   } else {
388     stream->Add("] <- ");
389   }
390
391   if (value() == NULL) {
392     ASSERT(hydrogen()->IsConstantHoleStore() &&
393            hydrogen()->value()->representation().IsDouble());
394     stream->Add("<the hole(nan)>");
395   } else {
396     value()->PrintTo(stream);
397   }
398 }
399
400
401 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
402   object()->PrintTo(stream);
403   stream->Add("[");
404   key()->PrintTo(stream);
405   stream->Add("] <- ");
406   value()->PrintTo(stream);
407 }
408
409
410 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
411   object()->PrintTo(stream);
412   stream->Add(" %p -> %p", *original_map(), *transitioned_map());
413 }
414
415
416 LPlatformChunk* LChunkBuilder::Build() {
417   ASSERT(is_unused());
418   chunk_ = new(zone()) LPlatformChunk(info(), graph());
419   LPhase phase("L_Building chunk", chunk_);
420   status_ = BUILDING;
421
422   // If compiling for OSR, reserve space for the unoptimized frame,
423   // which will be subsumed into this frame.
424   if (graph()->has_osr()) {
425     for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
426       chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
427     }
428   }
429
430   const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
431   for (int i = 0; i < blocks->length(); i++) {
432     HBasicBlock* next = NULL;
433     if (i < blocks->length() - 1) next = blocks->at(i + 1);
434     DoBasicBlock(blocks->at(i), next);
435     if (is_aborted()) return NULL;
436   }
437   status_ = DONE;
438   return chunk_;
439 }
440
441
442 void LChunkBuilder::Abort(BailoutReason reason) {
443   info()->set_bailout_reason(reason);
444   status_ = ABORTED;
445 }
446
447
448 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
449   return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
450                                   Register::ToAllocationIndex(reg));
451 }
452
453
454 LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
455   return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
456                                   XMMRegister::ToAllocationIndex(reg));
457 }
458
459
460 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
461   return Use(value, ToUnallocated(fixed_register));
462 }
463
464
465 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
466   return Use(value, ToUnallocated(reg));
467 }
468
469
470 LOperand* LChunkBuilder::UseRegister(HValue* value) {
471   return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
472 }
473
474
475 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
476   return Use(value,
477              new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
478                               LUnallocated::USED_AT_START));
479 }
480
481
482 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
483   return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
484 }
485
486
487 LOperand* LChunkBuilder::UseTempRegisterOrConstant(HValue* value) {
488   return value->IsConstant()
489       ? chunk_->DefineConstantOperand(HConstant::cast(value))
490       : UseTempRegister(value);
491 }
492
493
494 LOperand* LChunkBuilder::Use(HValue* value) {
495   return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
496 }
497
498
499 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
500   return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
501                                      LUnallocated::USED_AT_START));
502 }
503
504
505 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
506   return value->IsConstant()
507       ? chunk_->DefineConstantOperand(HConstant::cast(value))
508       : Use(value);
509 }
510
511
512 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
513   return value->IsConstant()
514       ? chunk_->DefineConstantOperand(HConstant::cast(value))
515       : UseAtStart(value);
516 }
517
518
519 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
520   return value->IsConstant()
521       ? chunk_->DefineConstantOperand(HConstant::cast(value))
522       : UseRegister(value);
523 }
524
525
526 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
527   return value->IsConstant()
528       ? chunk_->DefineConstantOperand(HConstant::cast(value))
529       : UseRegisterAtStart(value);
530 }
531
532
533 LOperand* LChunkBuilder::UseConstant(HValue* value) {
534   return chunk_->DefineConstantOperand(HConstant::cast(value));
535 }
536
537
538 LOperand* LChunkBuilder::UseAny(HValue* value) {
539   return value->IsConstant()
540       ? chunk_->DefineConstantOperand(HConstant::cast(value))
541       :  Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
542 }
543
544
545 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
546   if (value->EmitAtUses()) {
547     HInstruction* instr = HInstruction::cast(value);
548     VisitInstruction(instr);
549   }
550   operand->set_virtual_register(value->id());
551   return operand;
552 }
553
554
555 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
556                                     LUnallocated* result) {
557   result->set_virtual_register(current_instruction_->id());
558   instr->set_result(result);
559   return instr;
560 }
561
562
563 LInstruction* LChunkBuilder::DefineAsRegister(
564     LTemplateResultInstruction<1>* instr) {
565   return Define(instr,
566                 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
567 }
568
569
570 LInstruction* LChunkBuilder::DefineAsSpilled(
571     LTemplateResultInstruction<1>* instr,
572     int index) {
573   return Define(instr,
574                 new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
575 }
576
577
578 LInstruction* LChunkBuilder::DefineSameAsFirst(
579     LTemplateResultInstruction<1>* instr) {
580   return Define(instr,
581                 new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
582 }
583
584
585 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
586                                          Register reg) {
587   return Define(instr, ToUnallocated(reg));
588 }
589
590
591 LInstruction* LChunkBuilder::DefineFixedDouble(
592     LTemplateResultInstruction<1>* instr,
593     XMMRegister reg) {
594   return Define(instr, ToUnallocated(reg));
595 }
596
597
598 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
599   HEnvironment* hydrogen_env = current_block_->last_environment();
600   int argument_index_accumulator = 0;
601   ZoneList<HValue*> objects_to_materialize(0, zone());
602   instr->set_environment(CreateEnvironment(hydrogen_env,
603                                            &argument_index_accumulator,
604                                            &objects_to_materialize));
605   return instr;
606 }
607
608
609 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
610                                         HInstruction* hinstr,
611                                         CanDeoptimize can_deoptimize) {
612   info()->MarkAsNonDeferredCalling();
613
614 #ifdef DEBUG
615   instr->VerifyCall();
616 #endif
617   instr->MarkAsCall();
618   instr = AssignPointerMap(instr);
619
620   // If instruction does not have side-effects lazy deoptimization
621   // after the call will try to deoptimize to the point before the call.
622   // Thus we still need to attach environment to this call even if
623   // call sequence can not deoptimize eagerly.
624   bool needs_environment =
625       (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
626       !hinstr->HasObservableSideEffects();
627   if (needs_environment && !instr->HasEnvironment()) {
628     instr = AssignEnvironment(instr);
629     // We can't really figure out if the environment is needed or not.
630     instr->environment()->set_has_been_used();
631   }
632
633   return instr;
634 }
635
636
637 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
638   ASSERT(!instr->HasPointerMap());
639   instr->set_pointer_map(new(zone()) LPointerMap(zone()));
640   return instr;
641 }
642
643
644 LUnallocated* LChunkBuilder::TempRegister() {
645   LUnallocated* operand =
646       new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
647   int vreg = allocator_->GetVirtualRegister();
648   if (!allocator_->AllocationOk()) {
649     Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
650     vreg = 0;
651   }
652   operand->set_virtual_register(vreg);
653   return operand;
654 }
655
656
657 LOperand* LChunkBuilder::FixedTemp(Register reg) {
658   LUnallocated* operand = ToUnallocated(reg);
659   ASSERT(operand->HasFixedPolicy());
660   return operand;
661 }
662
663
664 LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
665   LUnallocated* operand = ToUnallocated(reg);
666   ASSERT(operand->HasFixedPolicy());
667   return operand;
668 }
669
670
671 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
672   return new(zone()) LLabel(instr->block());
673 }
674
675
676 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
677   return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
678 }
679
680
681 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
682   UNREACHABLE();
683   return NULL;
684 }
685
686
687 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
688   return AssignEnvironment(new(zone()) LDeoptimize);
689 }
690
691
692 LInstruction* LChunkBuilder::DoShift(Token::Value op,
693                                      HBitwiseBinaryOperation* instr) {
694   if (instr->representation().IsSmiOrInteger32()) {
695     ASSERT(instr->left()->representation().Equals(instr->representation()));
696     ASSERT(instr->right()->representation().Equals(instr->representation()));
697     LOperand* left = UseRegisterAtStart(instr->left());
698
699     HValue* right_value = instr->right();
700     LOperand* right = NULL;
701     int constant_value = 0;
702     bool does_deopt = false;
703     if (right_value->IsConstant()) {
704       HConstant* constant = HConstant::cast(right_value);
705       right = chunk_->DefineConstantOperand(constant);
706       constant_value = constant->Integer32Value() & 0x1f;
707       if (SmiValuesAre31Bits() && instr->representation().IsSmi() &&
708           constant_value > 0) {
709         // Left shift can deoptimize if we shift by > 0 and the result
710         // cannot be truncated to smi.
711         does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
712       }
713     } else {
714       right = UseFixed(right_value, rcx);
715     }
716
717     // Shift operations can only deoptimize if we do a logical shift by 0 and
718     // the result cannot be truncated to int32.
719     if (op == Token::SHR && constant_value == 0) {
720       if (FLAG_opt_safe_uint32_operations) {
721         does_deopt = !instr->CheckFlag(HInstruction::kUint32);
722       } else {
723         does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
724       }
725     }
726
727     LInstruction* result =
728         DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
729     return does_deopt ? AssignEnvironment(result) : result;
730   } else {
731     return DoArithmeticT(op, instr);
732   }
733 }
734
735
736 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
737                                            HArithmeticBinaryOperation* instr) {
738   ASSERT(instr->representation().IsDouble());
739   ASSERT(instr->left()->representation().IsDouble());
740   ASSERT(instr->right()->representation().IsDouble());
741   if (op == Token::MOD) {
742     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
743     LOperand* right = UseFixedDouble(instr->BetterRightOperand(), xmm1);
744     LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
745     return MarkAsCall(DefineSameAsFirst(result), instr);
746   } else {
747     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
748     LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
749     LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
750     return DefineSameAsFirst(result);
751   }
752 }
753
754
755 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
756                                            HBinaryOperation* instr) {
757   HValue* left = instr->left();
758   HValue* right = instr->right();
759   ASSERT(left->representation().IsTagged());
760   ASSERT(right->representation().IsTagged());
761   LOperand* context = UseFixed(instr->context(), rsi);
762   LOperand* left_operand = UseFixed(left, rdx);
763   LOperand* right_operand = UseFixed(right, rax);
764   LArithmeticT* result =
765       new(zone()) LArithmeticT(op, context, left_operand, right_operand);
766   return MarkAsCall(DefineFixed(result, rax), instr);
767 }
768
769
770 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
771   ASSERT(is_building());
772   current_block_ = block;
773   next_block_ = next_block;
774   if (block->IsStartBlock()) {
775     block->UpdateEnvironment(graph_->start_environment());
776     argument_count_ = 0;
777   } else if (block->predecessors()->length() == 1) {
778     // We have a single predecessor => copy environment and outgoing
779     // argument count from the predecessor.
780     ASSERT(block->phis()->length() == 0);
781     HBasicBlock* pred = block->predecessors()->at(0);
782     HEnvironment* last_environment = pred->last_environment();
783     ASSERT(last_environment != NULL);
784     // Only copy the environment, if it is later used again.
785     if (pred->end()->SecondSuccessor() == NULL) {
786       ASSERT(pred->end()->FirstSuccessor() == block);
787     } else {
788       if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
789           pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
790         last_environment = last_environment->Copy();
791       }
792     }
793     block->UpdateEnvironment(last_environment);
794     ASSERT(pred->argument_count() >= 0);
795     argument_count_ = pred->argument_count();
796   } else {
797     // We are at a state join => process phis.
798     HBasicBlock* pred = block->predecessors()->at(0);
799     // No need to copy the environment, it cannot be used later.
800     HEnvironment* last_environment = pred->last_environment();
801     for (int i = 0; i < block->phis()->length(); ++i) {
802       HPhi* phi = block->phis()->at(i);
803       if (phi->HasMergedIndex()) {
804         last_environment->SetValueAt(phi->merged_index(), phi);
805       }
806     }
807     for (int i = 0; i < block->deleted_phis()->length(); ++i) {
808       if (block->deleted_phis()->at(i) < last_environment->length()) {
809         last_environment->SetValueAt(block->deleted_phis()->at(i),
810                                      graph_->GetConstantUndefined());
811       }
812     }
813     block->UpdateEnvironment(last_environment);
814     // Pick up the outgoing argument count of one of the predecessors.
815     argument_count_ = pred->argument_count();
816   }
817   HInstruction* current = block->first();
818   int start = chunk_->instructions()->length();
819   while (current != NULL && !is_aborted()) {
820     // Code for constants in registers is generated lazily.
821     if (!current->EmitAtUses()) {
822       VisitInstruction(current);
823     }
824     current = current->next();
825   }
826   int end = chunk_->instructions()->length() - 1;
827   if (end >= start) {
828     block->set_first_instruction_index(start);
829     block->set_last_instruction_index(end);
830   }
831   block->set_argument_count(argument_count_);
832   next_block_ = NULL;
833   current_block_ = NULL;
834 }
835
836
837 void LChunkBuilder::VisitInstruction(HInstruction* current) {
838   HInstruction* old_current = current_instruction_;
839   current_instruction_ = current;
840
841   LInstruction* instr = NULL;
842   if (current->CanReplaceWithDummyUses()) {
843     if (current->OperandCount() == 0) {
844       instr = DefineAsRegister(new(zone()) LDummy());
845     } else {
846       ASSERT(!current->OperandAt(0)->IsControlInstruction());
847       instr = DefineAsRegister(new(zone())
848           LDummyUse(UseAny(current->OperandAt(0))));
849     }
850     for (int i = 1; i < current->OperandCount(); ++i) {
851       if (current->OperandAt(i)->IsControlInstruction()) continue;
852       LInstruction* dummy =
853           new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
854       dummy->set_hydrogen_value(current);
855       chunk_->AddInstruction(dummy, current_block_);
856     }
857   } else {
858     HBasicBlock* successor;
859     if (current->IsControlInstruction() &&
860         HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) &&
861         successor != NULL) {
862       instr = new(zone()) LGoto(successor);
863     } else {
864       instr = current->CompileToLithium(this);
865     }
866   }
867
868   argument_count_ += current->argument_delta();
869   ASSERT(argument_count_ >= 0);
870
871   if (instr != NULL) {
872     AddInstruction(instr, current);
873   }
874
875   current_instruction_ = old_current;
876 }
877
878
879 void LChunkBuilder::AddInstruction(LInstruction* instr,
880                                    HInstruction* hydrogen_val) {
881   // Associate the hydrogen instruction first, since we may need it for
882   // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
883   instr->set_hydrogen_value(hydrogen_val);
884
885 #if DEBUG
886   // Make sure that the lithium instruction has either no fixed register
887   // constraints in temps or the result OR no uses that are only used at
888   // start. If this invariant doesn't hold, the register allocator can decide
889   // to insert a split of a range immediately before the instruction due to an
890   // already allocated register needing to be used for the instruction's fixed
891   // register constraint. In this case, The register allocator won't see an
892   // interference between the split child and the use-at-start (it would if
893   // the it was just a plain use), so it is free to move the split child into
894   // the same register that is used for the use-at-start.
895   // See https://code.google.com/p/chromium/issues/detail?id=201590
896   if (!(instr->ClobbersRegisters() &&
897         instr->ClobbersDoubleRegisters(isolate()))) {
898     int fixed = 0;
899     int used_at_start = 0;
900     for (UseIterator it(instr); !it.Done(); it.Advance()) {
901       LUnallocated* operand = LUnallocated::cast(it.Current());
902       if (operand->IsUsedAtStart()) ++used_at_start;
903     }
904     if (instr->Output() != NULL) {
905       if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
906     }
907     for (TempIterator it(instr); !it.Done(); it.Advance()) {
908       LUnallocated* operand = LUnallocated::cast(it.Current());
909       if (operand->HasFixedPolicy()) ++fixed;
910     }
911     ASSERT(fixed == 0 || used_at_start == 0);
912   }
913 #endif
914
915   if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
916     instr = AssignPointerMap(instr);
917   }
918   if (FLAG_stress_environments && !instr->HasEnvironment()) {
919     instr = AssignEnvironment(instr);
920   }
921   chunk_->AddInstruction(instr, current_block_);
922
923   if (instr->IsCall()) {
924     HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
925     LInstruction* instruction_needing_environment = NULL;
926     if (hydrogen_val->HasObservableSideEffects()) {
927       HSimulate* sim = HSimulate::cast(hydrogen_val->next());
928       instruction_needing_environment = instr;
929       sim->ReplayEnvironment(current_block_->last_environment());
930       hydrogen_value_for_lazy_bailout = sim;
931     }
932     LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
933     bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
934     chunk_->AddInstruction(bailout, current_block_);
935     if (instruction_needing_environment != NULL) {
936       // Store the lazy deopt environment with the instruction if needed.
937       // Right now it is only used for LInstanceOfKnownGlobal.
938       instruction_needing_environment->
939           SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
940     }
941   }
942 }
943
944
945 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
946   return new(zone()) LGoto(instr->FirstSuccessor());
947 }
948
949
950 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
951   return new(zone()) LDebugBreak();
952 }
953
954
955 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
956   HValue* value = instr->value();
957   Representation r = value->representation();
958   HType type = value->type();
959   ToBooleanStub::Types expected = instr->expected_input_types();
960   if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
961
962   bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
963       type.IsJSArray() || type.IsHeapNumber() || type.IsString();
964   LInstruction* branch = new(zone()) LBranch(UseRegister(value));
965   if (!easy_case &&
966       ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) ||
967        !expected.IsGeneric())) {
968     branch = AssignEnvironment(branch);
969   }
970   return branch;
971 }
972
973
974 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
975   ASSERT(instr->value()->representation().IsTagged());
976   LOperand* value = UseRegisterAtStart(instr->value());
977   return new(zone()) LCmpMapAndBranch(value);
978 }
979
980
981 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
982   info()->MarkAsRequiresFrame();
983   return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
984 }
985
986
987 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
988   info()->MarkAsRequiresFrame();
989   return DefineAsRegister(new(zone()) LArgumentsElements);
990 }
991
992
993 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
994   LOperand* left = UseFixed(instr->left(), rax);
995   LOperand* right = UseFixed(instr->right(), rdx);
996   LOperand* context = UseFixed(instr->context(), rsi);
997   LInstanceOf* result = new(zone()) LInstanceOf(context, left, right);
998   return MarkAsCall(DefineFixed(result, rax), instr);
999 }
1000
1001
1002 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1003     HInstanceOfKnownGlobal* instr) {
1004   LInstanceOfKnownGlobal* result =
1005       new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->context(), rsi),
1006                                          UseFixed(instr->left(), rax),
1007                                          FixedTemp(rdi));
1008   return MarkAsCall(DefineFixed(result, rax), instr);
1009 }
1010
1011
1012 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1013   LOperand* receiver = UseRegister(instr->receiver());
1014   LOperand* function = UseRegisterAtStart(instr->function());
1015   LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
1016   return AssignEnvironment(DefineSameAsFirst(result));
1017 }
1018
1019
1020 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1021   LOperand* function = UseFixed(instr->function(), rdi);
1022   LOperand* receiver = UseFixed(instr->receiver(), rax);
1023   LOperand* length = UseFixed(instr->length(), rbx);
1024   LOperand* elements = UseFixed(instr->elements(), rcx);
1025   LApplyArguments* result = new(zone()) LApplyArguments(function,
1026                                                 receiver,
1027                                                 length,
1028                                                 elements);
1029   return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
1030 }
1031
1032
1033 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
1034   int argc = instr->OperandCount();
1035   for (int i = 0; i < argc; ++i) {
1036     LOperand* argument = UseOrConstant(instr->argument(i));
1037     AddInstruction(new(zone()) LPushArgument(argument), instr);
1038   }
1039   return NULL;
1040 }
1041
1042
1043 LInstruction* LChunkBuilder::DoStoreCodeEntry(
1044     HStoreCodeEntry* store_code_entry) {
1045   LOperand* function = UseRegister(store_code_entry->function());
1046   LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1047   return new(zone()) LStoreCodeEntry(function, code_object);
1048 }
1049
1050
1051 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1052     HInnerAllocatedObject* instr) {
1053   LOperand* base_object = UseRegisterAtStart(instr->base_object());
1054   LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
1055   return DefineAsRegister(
1056       new(zone()) LInnerAllocatedObject(base_object, offset));
1057 }
1058
1059
1060 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1061   return instr->HasNoUses()
1062       ? NULL
1063       : DefineAsRegister(new(zone()) LThisFunction);
1064 }
1065
1066
1067 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1068   if (instr->HasNoUses()) return NULL;
1069
1070   if (info()->IsStub()) {
1071     return DefineFixed(new(zone()) LContext, rsi);
1072   }
1073
1074   return DefineAsRegister(new(zone()) LContext);
1075 }
1076
1077
1078 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1079   LOperand* context = UseFixed(instr->context(), rsi);
1080   return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
1081 }
1082
1083
1084 LInstruction* LChunkBuilder::DoCallJSFunction(
1085     HCallJSFunction* instr) {
1086   LOperand* function = UseFixed(instr->function(), rdi);
1087
1088   LCallJSFunction* result = new(zone()) LCallJSFunction(function);
1089
1090   return MarkAsCall(DefineFixed(result, rax), instr);
1091 }
1092
1093
1094 LInstruction* LChunkBuilder::DoCallWithDescriptor(
1095     HCallWithDescriptor* instr) {
1096   const CallInterfaceDescriptor* descriptor = instr->descriptor();
1097
1098   LOperand* target = UseRegisterOrConstantAtStart(instr->target());
1099   ZoneList<LOperand*> ops(instr->OperandCount(), zone());
1100   ops.Add(target, zone());
1101   for (int i = 1; i < instr->OperandCount(); i++) {
1102     LOperand* op = UseFixed(instr->OperandAt(i),
1103         descriptor->GetParameterRegister(i - 1));
1104     ops.Add(op, zone());
1105   }
1106
1107   LCallWithDescriptor* result = new(zone()) LCallWithDescriptor(
1108       descriptor, ops, zone());
1109   return MarkAsCall(DefineFixed(result, rax), instr);
1110 }
1111
1112
1113 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1114   LOperand* context = UseFixed(instr->context(), rsi);
1115   LOperand* function = UseFixed(instr->function(), rdi);
1116   LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
1117   return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1118 }
1119
1120
1121 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1122   switch (instr->op()) {
1123     case kMathFloor: return DoMathFloor(instr);
1124     case kMathRound: return DoMathRound(instr);
1125     case kMathAbs: return DoMathAbs(instr);
1126     case kMathLog: return DoMathLog(instr);
1127     case kMathExp: return DoMathExp(instr);
1128     case kMathSqrt: return DoMathSqrt(instr);
1129     case kMathPowHalf: return DoMathPowHalf(instr);
1130     case kMathClz32: return DoMathClz32(instr);
1131     default:
1132       UNREACHABLE();
1133       return NULL;
1134   }
1135 }
1136
1137
1138 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1139   LOperand* input = UseRegisterAtStart(instr->value());
1140   LMathFloor* result = new(zone()) LMathFloor(input);
1141   return AssignEnvironment(DefineAsRegister(result));
1142 }
1143
1144
1145 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1146   LOperand* input = UseRegister(instr->value());
1147   LOperand* temp = FixedTemp(xmm4);
1148   LMathRound* result = new(zone()) LMathRound(input, temp);
1149   return AssignEnvironment(DefineAsRegister(result));
1150 }
1151
1152
1153 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1154   LOperand* context = UseAny(instr->context());
1155   LOperand* input = UseRegisterAtStart(instr->value());
1156   LInstruction* result =
1157       DefineSameAsFirst(new(zone()) LMathAbs(context, input));
1158   Representation r = instr->value()->representation();
1159   if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1160   if (!r.IsDouble()) result = AssignEnvironment(result);
1161   return result;
1162 }
1163
1164
1165 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1166   ASSERT(instr->representation().IsDouble());
1167   ASSERT(instr->value()->representation().IsDouble());
1168   LOperand* input = UseRegisterAtStart(instr->value());
1169   return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr);
1170 }
1171
1172
1173 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1174   LOperand* input = UseRegisterAtStart(instr->value());
1175   LMathClz32* result = new(zone()) LMathClz32(input);
1176   return DefineAsRegister(result);
1177 }
1178
1179
1180 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1181   ASSERT(instr->representation().IsDouble());
1182   ASSERT(instr->value()->representation().IsDouble());
1183   LOperand* value = UseTempRegister(instr->value());
1184   LOperand* temp1 = TempRegister();
1185   LOperand* temp2 = TempRegister();
1186   LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
1187   return DefineAsRegister(result);
1188 }
1189
1190
1191 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1192   LOperand* input = UseAtStart(instr->value());
1193   return DefineAsRegister(new(zone()) LMathSqrt(input));
1194 }
1195
1196
1197 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1198   LOperand* input = UseRegisterAtStart(instr->value());
1199   LMathPowHalf* result = new(zone()) LMathPowHalf(input);
1200   return DefineSameAsFirst(result);
1201 }
1202
1203
1204 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1205   LOperand* context = UseFixed(instr->context(), rsi);
1206   LOperand* constructor = UseFixed(instr->constructor(), rdi);
1207   LCallNew* result = new(zone()) LCallNew(context, constructor);
1208   return MarkAsCall(DefineFixed(result, rax), instr);
1209 }
1210
1211
1212 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1213   LOperand* context = UseFixed(instr->context(), rsi);
1214   LOperand* constructor = UseFixed(instr->constructor(), rdi);
1215   LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
1216   return MarkAsCall(DefineFixed(result, rax), instr);
1217 }
1218
1219
1220 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1221   LOperand* context = UseFixed(instr->context(), rsi);
1222   LOperand* function = UseFixed(instr->function(), rdi);
1223   LCallFunction* call = new(zone()) LCallFunction(context, function);
1224   return MarkAsCall(DefineFixed(call, rax), instr);
1225 }
1226
1227
1228 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1229   LOperand* context = UseFixed(instr->context(), rsi);
1230   LCallRuntime* result = new(zone()) LCallRuntime(context);
1231   return MarkAsCall(DefineFixed(result, rax), instr);
1232 }
1233
1234
1235 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1236   return DoShift(Token::ROR, instr);
1237 }
1238
1239
1240 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1241   return DoShift(Token::SHR, instr);
1242 }
1243
1244
1245 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1246   return DoShift(Token::SAR, instr);
1247 }
1248
1249
1250 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1251   return DoShift(Token::SHL, instr);
1252 }
1253
1254
1255 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1256   if (instr->representation().IsSmiOrInteger32()) {
1257     ASSERT(instr->left()->representation().Equals(instr->representation()));
1258     ASSERT(instr->right()->representation().Equals(instr->representation()));
1259     ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
1260
1261     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1262     LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1263     return DefineSameAsFirst(new(zone()) LBitI(left, right));
1264   } else {
1265     return DoArithmeticT(instr->op(), instr);
1266   }
1267 }
1268
1269
1270 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1271   ASSERT(instr->representation().IsSmiOrInteger32());
1272   ASSERT(instr->left()->representation().Equals(instr->representation()));
1273   ASSERT(instr->right()->representation().Equals(instr->representation()));
1274   LOperand* dividend = UseRegister(instr->left());
1275   int32_t divisor = instr->right()->GetInteger32Constant();
1276   LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
1277           dividend, divisor));
1278   if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1279       (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
1280       (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1281        divisor != 1 && divisor != -1)) {
1282     result = AssignEnvironment(result);
1283   }
1284   return result;
1285 }
1286
1287
1288 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1289   ASSERT(instr->representation().IsInteger32());
1290   ASSERT(instr->left()->representation().Equals(instr->representation()));
1291   ASSERT(instr->right()->representation().Equals(instr->representation()));
1292   LOperand* dividend = UseRegister(instr->left());
1293   int32_t divisor = instr->right()->GetInteger32Constant();
1294   LOperand* temp1 = FixedTemp(rax);
1295   LOperand* temp2 = FixedTemp(rdx);
1296   LInstruction* result = DefineFixed(new(zone()) LDivByConstI(
1297           dividend, divisor, temp1, temp2), rdx);
1298   if (divisor == 0 ||
1299       (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1300       !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1301     result = AssignEnvironment(result);
1302   }
1303   return result;
1304 }
1305
1306
1307 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
1308   ASSERT(instr->representation().IsSmiOrInteger32());
1309   ASSERT(instr->left()->representation().Equals(instr->representation()));
1310   ASSERT(instr->right()->representation().Equals(instr->representation()));
1311   LOperand* dividend = UseFixed(instr->left(), rax);
1312   LOperand* divisor = UseRegister(instr->right());
1313   LOperand* temp = FixedTemp(rdx);
1314   LInstruction* result = DefineFixed(new(zone()) LDivI(
1315           dividend, divisor, temp), rax);
1316   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1317       instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1318       instr->CheckFlag(HValue::kCanOverflow) ||
1319       !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1320     result = AssignEnvironment(result);
1321   }
1322   return result;
1323 }
1324
1325
1326 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1327   if (instr->representation().IsSmiOrInteger32()) {
1328     if (instr->RightIsPowerOf2()) {
1329       return DoDivByPowerOf2I(instr);
1330     } else if (instr->right()->IsConstant()) {
1331       return DoDivByConstI(instr);
1332     } else {
1333       return DoDivI(instr);
1334     }
1335   } else if (instr->representation().IsDouble()) {
1336     return DoArithmeticD(Token::DIV, instr);
1337   } else {
1338     return DoArithmeticT(Token::DIV, instr);
1339   }
1340 }
1341
1342
1343 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1344   LOperand* dividend = UseRegisterAtStart(instr->left());
1345   int32_t divisor = instr->right()->GetInteger32Constant();
1346   LInstruction* result = DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(
1347           dividend, divisor));
1348   if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1349       (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
1350     result = AssignEnvironment(result);
1351   }
1352   return result;
1353 }
1354
1355
1356 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1357   ASSERT(instr->representation().IsInteger32());
1358   ASSERT(instr->left()->representation().Equals(instr->representation()));
1359   ASSERT(instr->right()->representation().Equals(instr->representation()));
1360   LOperand* dividend = UseRegister(instr->left());
1361   int32_t divisor = instr->right()->GetInteger32Constant();
1362   LOperand* temp1 = FixedTemp(rax);
1363   LOperand* temp2 = FixedTemp(rdx);
1364   LOperand* temp3 =
1365       ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
1366        (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
1367       NULL : TempRegister();
1368   LInstruction* result =
1369       DefineFixed(new(zone()) LFlooringDivByConstI(dividend,
1370                                                    divisor,
1371                                                    temp1,
1372                                                    temp2,
1373                                                    temp3),
1374                   rdx);
1375   if (divisor == 0 ||
1376       (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
1377     result = AssignEnvironment(result);
1378   }
1379   return result;
1380 }
1381
1382
1383 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1384   ASSERT(instr->representation().IsSmiOrInteger32());
1385   ASSERT(instr->left()->representation().Equals(instr->representation()));
1386   ASSERT(instr->right()->representation().Equals(instr->representation()));
1387   LOperand* dividend = UseFixed(instr->left(), rax);
1388   LOperand* divisor = UseRegister(instr->right());
1389   LOperand* temp = FixedTemp(rdx);
1390   LInstruction* result = DefineFixed(new(zone()) LFlooringDivI(
1391           dividend, divisor, temp), rax);
1392   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1393       instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1394       instr->CheckFlag(HValue::kCanOverflow)) {
1395     result = AssignEnvironment(result);
1396   }
1397   return result;
1398 }
1399
1400
1401 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1402   if (instr->RightIsPowerOf2()) {
1403     return DoFlooringDivByPowerOf2I(instr);
1404   } else if (instr->right()->IsConstant()) {
1405     return DoFlooringDivByConstI(instr);
1406   } else {
1407     return DoFlooringDivI(instr);
1408   }
1409 }
1410
1411
1412 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1413   ASSERT(instr->representation().IsSmiOrInteger32());
1414   ASSERT(instr->left()->representation().Equals(instr->representation()));
1415   ASSERT(instr->right()->representation().Equals(instr->representation()));
1416   LOperand* dividend = UseRegisterAtStart(instr->left());
1417   int32_t divisor = instr->right()->GetInteger32Constant();
1418   LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
1419           dividend, divisor));
1420   if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1421     result = AssignEnvironment(result);
1422   }
1423   return result;
1424 }
1425
1426
1427 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1428   ASSERT(instr->representation().IsSmiOrInteger32());
1429   ASSERT(instr->left()->representation().Equals(instr->representation()));
1430   ASSERT(instr->right()->representation().Equals(instr->representation()));
1431   LOperand* dividend = UseRegister(instr->left());
1432   int32_t divisor = instr->right()->GetInteger32Constant();
1433   LOperand* temp1 = FixedTemp(rax);
1434   LOperand* temp2 = FixedTemp(rdx);
1435   LInstruction* result = DefineFixed(new(zone()) LModByConstI(
1436           dividend, divisor, temp1, temp2), rax);
1437   if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1438     result = AssignEnvironment(result);
1439   }
1440   return result;
1441 }
1442
1443
1444 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1445   ASSERT(instr->representation().IsSmiOrInteger32());
1446   ASSERT(instr->left()->representation().Equals(instr->representation()));
1447   ASSERT(instr->right()->representation().Equals(instr->representation()));
1448   LOperand* dividend = UseFixed(instr->left(), rax);
1449   LOperand* divisor = UseRegister(instr->right());
1450   LOperand* temp = FixedTemp(rdx);
1451   LInstruction* result = DefineFixed(new(zone()) LModI(
1452           dividend, divisor, temp), rdx);
1453   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1454       instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1455     result = AssignEnvironment(result);
1456   }
1457   return result;
1458 }
1459
1460
1461 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1462   if (instr->representation().IsSmiOrInteger32()) {
1463     if (instr->RightIsPowerOf2()) {
1464       return DoModByPowerOf2I(instr);
1465     } else if (instr->right()->IsConstant()) {
1466       return DoModByConstI(instr);
1467     } else {
1468       return DoModI(instr);
1469     }
1470   } else if (instr->representation().IsDouble()) {
1471     return DoArithmeticD(Token::MOD, instr);
1472   } else {
1473     return DoArithmeticT(Token::MOD, instr);
1474   }
1475 }
1476
1477
1478 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1479   if (instr->representation().IsSmiOrInteger32()) {
1480     ASSERT(instr->left()->representation().Equals(instr->representation()));
1481     ASSERT(instr->right()->representation().Equals(instr->representation()));
1482     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1483     LOperand* right = UseOrConstant(instr->BetterRightOperand());
1484     LMulI* mul = new(zone()) LMulI(left, right);
1485     if (instr->CheckFlag(HValue::kCanOverflow) ||
1486         instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1487       AssignEnvironment(mul);
1488     }
1489     return DefineSameAsFirst(mul);
1490   } else if (instr->representation().IsDouble()) {
1491     return DoArithmeticD(Token::MUL, instr);
1492   } else {
1493     return DoArithmeticT(Token::MUL, instr);
1494   }
1495 }
1496
1497
1498 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1499   if (instr->representation().IsSmiOrInteger32()) {
1500     ASSERT(instr->left()->representation().Equals(instr->representation()));
1501     ASSERT(instr->right()->representation().Equals(instr->representation()));
1502     LOperand* left = UseRegisterAtStart(instr->left());
1503     LOperand* right = UseOrConstantAtStart(instr->right());
1504     LSubI* sub = new(zone()) LSubI(left, right);
1505     LInstruction* result = DefineSameAsFirst(sub);
1506     if (instr->CheckFlag(HValue::kCanOverflow)) {
1507       result = AssignEnvironment(result);
1508     }
1509     return result;
1510   } else if (instr->representation().IsDouble()) {
1511     return DoArithmeticD(Token::SUB, instr);
1512   } else {
1513     return DoArithmeticT(Token::SUB, instr);
1514   }
1515 }
1516
1517
1518 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1519   if (instr->representation().IsSmiOrInteger32()) {
1520     // Check to see if it would be advantageous to use an lea instruction rather
1521     // than an add. This is the case when no overflow check is needed and there
1522     // are multiple uses of the add's inputs, so using a 3-register add will
1523     // preserve all input values for later uses.
1524     bool use_lea = LAddI::UseLea(instr);
1525     ASSERT(instr->left()->representation().Equals(instr->representation()));
1526     ASSERT(instr->right()->representation().Equals(instr->representation()));
1527     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1528     HValue* right_candidate = instr->BetterRightOperand();
1529     LOperand* right;
1530     if (SmiValuesAre32Bits() && instr->representation().IsSmi()) {
1531       // We cannot add a tagged immediate to a tagged value,
1532       // so we request it in a register.
1533       right = UseRegisterAtStart(right_candidate);
1534     } else {
1535       right = use_lea ? UseRegisterOrConstantAtStart(right_candidate)
1536                       : UseOrConstantAtStart(right_candidate);
1537     }
1538     LAddI* add = new(zone()) LAddI(left, right);
1539     bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1540     LInstruction* result = use_lea ? DefineAsRegister(add)
1541                                    : DefineSameAsFirst(add);
1542     if (can_overflow) {
1543       result = AssignEnvironment(result);
1544     }
1545     return result;
1546   } else if (instr->representation().IsExternal()) {
1547     ASSERT(instr->left()->representation().IsExternal());
1548     ASSERT(instr->right()->representation().IsInteger32());
1549     ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
1550     bool use_lea = LAddI::UseLea(instr);
1551     LOperand* left = UseRegisterAtStart(instr->left());
1552     HValue* right_candidate = instr->right();
1553     LOperand* right = use_lea
1554         ? UseRegisterOrConstantAtStart(right_candidate)
1555         : UseOrConstantAtStart(right_candidate);
1556     LAddI* add = new(zone()) LAddI(left, right);
1557     LInstruction* result = use_lea
1558         ? DefineAsRegister(add)
1559         : DefineSameAsFirst(add);
1560     return result;
1561   } else if (instr->representation().IsDouble()) {
1562     return DoArithmeticD(Token::ADD, instr);
1563   } else {
1564     return DoArithmeticT(Token::ADD, instr);
1565   }
1566   return NULL;
1567 }
1568
1569
1570 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1571   LOperand* left = NULL;
1572   LOperand* right = NULL;
1573   ASSERT(instr->left()->representation().Equals(instr->representation()));
1574   ASSERT(instr->right()->representation().Equals(instr->representation()));
1575   if (instr->representation().IsSmi()) {
1576     left = UseRegisterAtStart(instr->BetterLeftOperand());
1577     right = UseAtStart(instr->BetterRightOperand());
1578   } else if (instr->representation().IsInteger32()) {
1579     left = UseRegisterAtStart(instr->BetterLeftOperand());
1580     right = UseOrConstantAtStart(instr->BetterRightOperand());
1581   } else {
1582     ASSERT(instr->representation().IsDouble());
1583     left = UseRegisterAtStart(instr->left());
1584     right = UseRegisterAtStart(instr->right());
1585   }
1586   LMathMinMax* minmax = new(zone()) LMathMinMax(left, right);
1587   return DefineSameAsFirst(minmax);
1588 }
1589
1590
1591 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1592   ASSERT(instr->representation().IsDouble());
1593   // We call a C function for double power. It can't trigger a GC.
1594   // We need to use fixed result register for the call.
1595   Representation exponent_type = instr->right()->representation();
1596   ASSERT(instr->left()->representation().IsDouble());
1597   LOperand* left = UseFixedDouble(instr->left(), xmm2);
1598   LOperand* right = exponent_type.IsDouble() ?
1599       UseFixedDouble(instr->right(), xmm1) : UseFixed(instr->right(), rdx);
1600   LPower* result = new(zone()) LPower(left, right);
1601   return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
1602                     CAN_DEOPTIMIZE_EAGERLY);
1603 }
1604
1605
1606 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1607   ASSERT(instr->left()->representation().IsTagged());
1608   ASSERT(instr->right()->representation().IsTagged());
1609   LOperand* context = UseFixed(instr->context(), rsi);
1610   LOperand* left = UseFixed(instr->left(), rdx);
1611   LOperand* right = UseFixed(instr->right(), rax);
1612   LCmpT* result = new(zone()) LCmpT(context, left, right);
1613   return MarkAsCall(DefineFixed(result, rax), instr);
1614 }
1615
1616
1617 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1618     HCompareNumericAndBranch* instr) {
1619   Representation r = instr->representation();
1620   if (r.IsSmiOrInteger32()) {
1621     ASSERT(instr->left()->representation().Equals(r));
1622     ASSERT(instr->right()->representation().Equals(r));
1623     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1624     LOperand* right = UseOrConstantAtStart(instr->right());
1625     return new(zone()) LCompareNumericAndBranch(left, right);
1626   } else {
1627     ASSERT(r.IsDouble());
1628     ASSERT(instr->left()->representation().IsDouble());
1629     ASSERT(instr->right()->representation().IsDouble());
1630     LOperand* left;
1631     LOperand* right;
1632     if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1633       left = UseRegisterOrConstantAtStart(instr->left());
1634       right = UseRegisterOrConstantAtStart(instr->right());
1635     } else {
1636       left = UseRegisterAtStart(instr->left());
1637       right = UseRegisterAtStart(instr->right());
1638     }
1639     return new(zone()) LCompareNumericAndBranch(left, right);
1640   }
1641 }
1642
1643
1644 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1645     HCompareObjectEqAndBranch* instr) {
1646   LOperand* left = UseRegisterAtStart(instr->left());
1647   LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1648   return new(zone()) LCmpObjectEqAndBranch(left, right);
1649 }
1650
1651
1652 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1653     HCompareHoleAndBranch* instr) {
1654   LOperand* value = UseRegisterAtStart(instr->value());
1655   return new(zone()) LCmpHoleAndBranch(value);
1656 }
1657
1658
1659 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1660     HCompareMinusZeroAndBranch* instr) {
1661   LOperand* value = UseRegister(instr->value());
1662   return new(zone()) LCompareMinusZeroAndBranch(value);
1663 }
1664
1665
1666 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1667   ASSERT(instr->value()->representation().IsTagged());
1668   return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
1669 }
1670
1671
1672 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1673   ASSERT(instr->value()->representation().IsTagged());
1674   LOperand* value = UseRegisterAtStart(instr->value());
1675   LOperand* temp = TempRegister();
1676   return new(zone()) LIsStringAndBranch(value, temp);
1677 }
1678
1679
1680 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1681   ASSERT(instr->value()->representation().IsTagged());
1682   return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1683 }
1684
1685
1686 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1687     HIsUndetectableAndBranch* instr) {
1688   ASSERT(instr->value()->representation().IsTagged());
1689   LOperand* value = UseRegisterAtStart(instr->value());
1690   LOperand* temp = TempRegister();
1691   return new(zone()) LIsUndetectableAndBranch(value, temp);
1692 }
1693
1694
1695 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1696     HStringCompareAndBranch* instr) {
1697
1698   ASSERT(instr->left()->representation().IsTagged());
1699   ASSERT(instr->right()->representation().IsTagged());
1700   LOperand* context = UseFixed(instr->context(), rsi);
1701   LOperand* left = UseFixed(instr->left(), rdx);
1702   LOperand* right = UseFixed(instr->right(), rax);
1703   LStringCompareAndBranch* result =
1704       new(zone()) LStringCompareAndBranch(context, left, right);
1705
1706   return MarkAsCall(result, instr);
1707 }
1708
1709
1710 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1711     HHasInstanceTypeAndBranch* instr) {
1712   ASSERT(instr->value()->representation().IsTagged());
1713   LOperand* value = UseRegisterAtStart(instr->value());
1714   return new(zone()) LHasInstanceTypeAndBranch(value);
1715 }
1716
1717
1718 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1719     HGetCachedArrayIndex* instr)  {
1720   ASSERT(instr->value()->representation().IsTagged());
1721   LOperand* value = UseRegisterAtStart(instr->value());
1722
1723   return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
1724 }
1725
1726
1727 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1728     HHasCachedArrayIndexAndBranch* instr) {
1729   ASSERT(instr->value()->representation().IsTagged());
1730   LOperand* value = UseRegisterAtStart(instr->value());
1731   return new(zone()) LHasCachedArrayIndexAndBranch(value);
1732 }
1733
1734
1735 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1736     HClassOfTestAndBranch* instr) {
1737   LOperand* value = UseRegister(instr->value());
1738   return new(zone()) LClassOfTestAndBranch(value,
1739                                            TempRegister(),
1740                                            TempRegister());
1741 }
1742
1743
1744 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1745   LOperand* map = UseRegisterAtStart(instr->value());
1746   return DefineAsRegister(new(zone()) LMapEnumLength(map));
1747 }
1748
1749
1750 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1751   LOperand* object = UseFixed(instr->value(), rax);
1752   LDateField* result = new(zone()) LDateField(object, instr->index());
1753   return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
1754 }
1755
1756
1757 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1758   LOperand* string = UseRegisterAtStart(instr->string());
1759   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1760   return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index));
1761 }
1762
1763
1764 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1765   LOperand* string = UseRegisterAtStart(instr->string());
1766   LOperand* index = FLAG_debug_code
1767       ? UseRegisterAtStart(instr->index())
1768       : UseRegisterOrConstantAtStart(instr->index());
1769   LOperand* value = FLAG_debug_code
1770       ? UseRegisterAtStart(instr->value())
1771       : UseRegisterOrConstantAtStart(instr->value());
1772   LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), rsi) : NULL;
1773   LInstruction* result = new(zone()) LSeqStringSetChar(context, string,
1774                                                        index, value);
1775   if (FLAG_debug_code) {
1776     result = MarkAsCall(result, instr);
1777   }
1778   return result;
1779 }
1780
1781
1782 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1783   if (!FLAG_debug_code && instr->skip_check()) return NULL;
1784   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1785   LOperand* length = !index->IsConstantOperand()
1786       ? UseOrConstantAtStart(instr->length())
1787       : UseAtStart(instr->length());
1788   LInstruction* result = new(zone()) LBoundsCheck(index, length);
1789   if (!FLAG_debug_code || !instr->skip_check()) {
1790     result = AssignEnvironment(result);
1791   }
1792   return result;
1793 }
1794
1795
1796 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1797     HBoundsCheckBaseIndexInformation* instr) {
1798   UNREACHABLE();
1799   return NULL;
1800 }
1801
1802
1803 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1804   // The control instruction marking the end of a block that completed
1805   // abruptly (e.g., threw an exception).  There is nothing specific to do.
1806   return NULL;
1807 }
1808
1809
1810 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1811   return NULL;
1812 }
1813
1814
1815 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1816   // All HForceRepresentation instructions should be eliminated in the
1817   // representation change phase of Hydrogen.
1818   UNREACHABLE();
1819   return NULL;
1820 }
1821
1822
1823 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1824   Representation from = instr->from();
1825   Representation to = instr->to();
1826   HValue* val = instr->value();
1827   if (from.IsSmi()) {
1828     if (to.IsTagged()) {
1829       LOperand* value = UseRegister(val);
1830       return DefineSameAsFirst(new(zone()) LDummyUse(value));
1831     }
1832     from = Representation::Tagged();
1833   }
1834   if (from.IsTagged()) {
1835     if (to.IsDouble()) {
1836       LOperand* value = UseRegister(val);
1837       LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value));
1838       if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1839       return result;
1840     } else if (to.IsSmi()) {
1841       LOperand* value = UseRegister(val);
1842       if (val->type().IsSmi()) {
1843         return DefineSameAsFirst(new(zone()) LDummyUse(value));
1844       }
1845       return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
1846     } else {
1847       ASSERT(to.IsInteger32());
1848       if (val->type().IsSmi() || val->representation().IsSmi()) {
1849         LOperand* value = UseRegister(val);
1850         return DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
1851       } else {
1852         LOperand* value = UseRegister(val);
1853         bool truncating = instr->CanTruncateToInt32();
1854         LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
1855         LInstruction* result =
1856             DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp));
1857         if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1858         return result;
1859       }
1860     }
1861   } else if (from.IsDouble()) {
1862     if (to.IsTagged()) {
1863       info()->MarkAsDeferredCalling();
1864       LOperand* value = UseRegister(val);
1865       LOperand* temp = TempRegister();
1866       LUnallocated* result_temp = TempRegister();
1867       LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
1868       return AssignPointerMap(Define(result, result_temp));
1869     } else if (to.IsSmi()) {
1870       LOperand* value = UseRegister(val);
1871       return AssignEnvironment(
1872           DefineAsRegister(new(zone()) LDoubleToSmi(value)));
1873     } else {
1874       ASSERT(to.IsInteger32());
1875       LOperand* value = UseRegister(val);
1876       LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value));
1877       if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result);
1878       return result;
1879     }
1880   } else if (from.IsInteger32()) {
1881     info()->MarkAsDeferredCalling();
1882     if (to.IsTagged()) {
1883       if (!instr->CheckFlag(HValue::kCanOverflow)) {
1884         LOperand* value = UseRegister(val);
1885         return DefineAsRegister(new(zone()) LSmiTag(value));
1886       } else if (val->CheckFlag(HInstruction::kUint32)) {
1887         LOperand* value = UseRegister(val);
1888         LOperand* temp1 = TempRegister();
1889         LOperand* temp2 = FixedTemp(xmm1);
1890         LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2);
1891         return AssignPointerMap(DefineSameAsFirst(result));
1892       } else {
1893         LOperand* value = UseRegister(val);
1894         LOperand* temp1 = SmiValuesAre32Bits() ? NULL : TempRegister();
1895         LOperand* temp2 = SmiValuesAre32Bits() ? NULL : FixedTemp(xmm1);
1896         LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2);
1897         return AssignPointerMap(DefineSameAsFirst(result));
1898       }
1899     } else if (to.IsSmi()) {
1900       LOperand* value = UseRegister(val);
1901       LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value));
1902       if (instr->CheckFlag(HValue::kCanOverflow)) {
1903         result = AssignEnvironment(result);
1904       }
1905       return result;
1906     } else {
1907       ASSERT(to.IsDouble());
1908       if (val->CheckFlag(HInstruction::kUint32)) {
1909         return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val)));
1910       } else {
1911         LOperand* value = Use(val);
1912         return DefineAsRegister(new(zone()) LInteger32ToDouble(value));
1913       }
1914     }
1915   }
1916   UNREACHABLE();
1917   return NULL;
1918 }
1919
1920
1921 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
1922   LOperand* value = UseRegisterAtStart(instr->value());
1923   LInstruction* result = new(zone()) LCheckNonSmi(value);
1924   if (!instr->value()->type().IsHeapObject()) {
1925     result = AssignEnvironment(result);
1926   }
1927   return result;
1928 }
1929
1930
1931 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1932   LOperand* value = UseRegisterAtStart(instr->value());
1933   return AssignEnvironment(new(zone()) LCheckSmi(value));
1934 }
1935
1936
1937 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1938   LOperand* value = UseRegisterAtStart(instr->value());
1939   LCheckInstanceType* result = new(zone()) LCheckInstanceType(value);
1940   return AssignEnvironment(result);
1941 }
1942
1943
1944 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
1945   LOperand* value = UseRegisterAtStart(instr->value());
1946   return AssignEnvironment(new(zone()) LCheckValue(value));
1947 }
1948
1949
1950 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1951   if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
1952   LOperand* value = UseRegisterAtStart(instr->value());
1953   LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value));
1954   if (instr->HasMigrationTarget()) {
1955     info()->MarkAsDeferredCalling();
1956     result = AssignPointerMap(result);
1957   }
1958   return result;
1959 }
1960
1961
1962 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1963   HValue* value = instr->value();
1964   Representation input_rep = value->representation();
1965   LOperand* reg = UseRegister(value);
1966   if (input_rep.IsDouble()) {
1967     return DefineAsRegister(new(zone()) LClampDToUint8(reg));
1968   } else if (input_rep.IsInteger32()) {
1969     return DefineSameAsFirst(new(zone()) LClampIToUint8(reg));
1970   } else {
1971     ASSERT(input_rep.IsSmiOrTagged());
1972     // Register allocator doesn't (yet) support allocation of double
1973     // temps. Reserve xmm1 explicitly.
1974     LClampTToUint8* result = new(zone()) LClampTToUint8(reg,
1975                                                         FixedTemp(xmm1));
1976     return AssignEnvironment(DefineSameAsFirst(result));
1977   }
1978 }
1979
1980
1981 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
1982   HValue* value = instr->value();
1983   ASSERT(value->representation().IsDouble());
1984   return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
1985 }
1986
1987
1988 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
1989   LOperand* lo = UseRegister(instr->lo());
1990   LOperand* hi = UseRegister(instr->hi());
1991   return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
1992 }
1993
1994
1995 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1996   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), rsi) : NULL;
1997   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1998   return new(zone()) LReturn(
1999       UseFixed(instr->value(), rax), context, parameter_count);
2000 }
2001
2002
2003 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
2004   Representation r = instr->representation();
2005   if (r.IsSmi()) {
2006     return DefineAsRegister(new(zone()) LConstantS);
2007   } else if (r.IsInteger32()) {
2008     return DefineAsRegister(new(zone()) LConstantI);
2009   } else if (r.IsDouble()) {
2010     LOperand* temp = TempRegister();
2011     return DefineAsRegister(new(zone()) LConstantD(temp));
2012   } else if (r.IsExternal()) {
2013     return DefineAsRegister(new(zone()) LConstantE);
2014   } else if (r.IsTagged()) {
2015     return DefineAsRegister(new(zone()) LConstantT);
2016   } else {
2017     UNREACHABLE();
2018     return NULL;
2019   }
2020 }
2021
2022
2023 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
2024   LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
2025   return instr->RequiresHoleCheck()
2026       ? AssignEnvironment(DefineAsRegister(result))
2027       : DefineAsRegister(result);
2028 }
2029
2030
2031 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2032   LOperand* context = UseFixed(instr->context(), rsi);
2033   LOperand* global_object = UseFixed(instr->global_object(), rax);
2034   LLoadGlobalGeneric* result =
2035       new(zone()) LLoadGlobalGeneric(context, global_object);
2036   return MarkAsCall(DefineFixed(result, rax), instr);
2037 }
2038
2039
2040 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2041   LOperand* value = UseRegister(instr->value());
2042   // Use a temp to avoid reloading the cell value address in the case where
2043   // we perform a hole check.
2044   return instr->RequiresHoleCheck()
2045       ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
2046       : new(zone()) LStoreGlobalCell(value, NULL);
2047 }
2048
2049
2050 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
2051   LOperand* context = UseRegisterAtStart(instr->value());
2052   LInstruction* result =
2053       DefineAsRegister(new(zone()) LLoadContextSlot(context));
2054   if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2055     result = AssignEnvironment(result);
2056   }
2057   return result;
2058 }
2059
2060
2061 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
2062   LOperand* context;
2063   LOperand* value;
2064   LOperand* temp;
2065   context = UseRegister(instr->context());
2066   if (instr->NeedsWriteBarrier()) {
2067     value = UseTempRegister(instr->value());
2068     temp = TempRegister();
2069   } else {
2070     value = UseRegister(instr->value());
2071     temp = NULL;
2072   }
2073   LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
2074   if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2075     result = AssignEnvironment(result);
2076   }
2077   return result;
2078 }
2079
2080
2081 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
2082   // Use the special mov rax, moffs64 encoding for external
2083   // memory accesses with 64-bit word-sized values.
2084   if (instr->access().IsExternalMemory() &&
2085       instr->access().offset() == 0 &&
2086       (instr->access().representation().IsSmi() ||
2087        instr->access().representation().IsTagged() ||
2088        instr->access().representation().IsHeapObject() ||
2089        instr->access().representation().IsExternal())) {
2090     LOperand* obj = UseRegisterOrConstantAtStart(instr->object());
2091     return DefineFixed(new(zone()) LLoadNamedField(obj), rax);
2092   }
2093   LOperand* obj = UseRegisterAtStart(instr->object());
2094   return DefineAsRegister(new(zone()) LLoadNamedField(obj));
2095 }
2096
2097
2098 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2099   LOperand* context = UseFixed(instr->context(), rsi);
2100   LOperand* object = UseFixed(instr->object(), rax);
2101   LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
2102   return MarkAsCall(DefineFixed(result, rax), instr);
2103 }
2104
2105
2106 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2107     HLoadFunctionPrototype* instr) {
2108   return AssignEnvironment(DefineAsRegister(
2109       new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
2110 }
2111
2112
2113 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2114   return DefineAsRegister(new(zone()) LLoadRoot);
2115 }
2116
2117
2118 void LChunkBuilder::FindDehoistedKeyDefinitions(HValue* candidate) {
2119   // We sign extend the dehoisted key at the definition point when the pointer
2120   // size is 64-bit. For x32 port, we sign extend the dehoisted key at the use
2121   // points and should not invoke this function. We can't use STATIC_ASSERT
2122   // here as the pointer size is 32-bit for x32.
2123   ASSERT(kPointerSize == kInt64Size);
2124   BitVector* dehoisted_key_ids = chunk_->GetDehoistedKeyIds();
2125   if (dehoisted_key_ids->Contains(candidate->id())) return;
2126   dehoisted_key_ids->Add(candidate->id());
2127   if (!candidate->IsPhi()) return;
2128   for (int i = 0; i < candidate->OperandCount(); ++i) {
2129     FindDehoistedKeyDefinitions(candidate->OperandAt(i));
2130   }
2131 }
2132
2133
2134 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
2135   ASSERT((kPointerSize == kInt64Size &&
2136           instr->key()->representation().IsInteger32()) ||
2137          (kPointerSize == kInt32Size &&
2138           instr->key()->representation().IsSmiOrInteger32()));
2139   ElementsKind elements_kind = instr->elements_kind();
2140   LOperand* key = NULL;
2141   LInstruction* result = NULL;
2142
2143   if (kPointerSize == kInt64Size) {
2144     key = UseRegisterOrConstantAtStart(instr->key());
2145   } else {
2146     bool clobbers_key = ExternalArrayOpRequiresTemp(
2147         instr->key()->representation(), elements_kind);
2148     key = clobbers_key
2149         ? UseTempRegister(instr->key())
2150         : UseRegisterOrConstantAtStart(instr->key());
2151   }
2152
2153   if ((kPointerSize == kInt64Size) && instr->IsDehoisted()) {
2154     FindDehoistedKeyDefinitions(instr->key());
2155   }
2156
2157   if (!instr->is_typed_elements()) {
2158     LOperand* obj = UseRegisterAtStart(instr->elements());
2159     result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
2160   } else {
2161     ASSERT(
2162         (instr->representation().IsInteger32() &&
2163          !(IsDoubleOrFloatElementsKind(elements_kind))) ||
2164         (instr->representation().IsDouble() &&
2165          (IsDoubleOrFloatElementsKind(elements_kind))));
2166     LOperand* backing_store = UseRegister(instr->elements());
2167     result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
2168   }
2169
2170   if ((instr->is_external() || instr->is_fixed_typed_array()) ?
2171       // see LCodeGen::DoLoadKeyedExternalArray
2172       ((elements_kind == EXTERNAL_UINT32_ELEMENTS ||
2173         elements_kind == UINT32_ELEMENTS) &&
2174        !instr->CheckFlag(HInstruction::kUint32)) :
2175       // see LCodeGen::DoLoadKeyedFixedDoubleArray and
2176       // LCodeGen::DoLoadKeyedFixedArray
2177       instr->RequiresHoleCheck()) {
2178     result = AssignEnvironment(result);
2179   }
2180   return result;
2181 }
2182
2183
2184 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2185   LOperand* context = UseFixed(instr->context(), rsi);
2186   LOperand* object = UseFixed(instr->object(), rdx);
2187   LOperand* key = UseFixed(instr->key(), rax);
2188
2189   LLoadKeyedGeneric* result =
2190       new(zone()) LLoadKeyedGeneric(context, object, key);
2191   return MarkAsCall(DefineFixed(result, rax), instr);
2192 }
2193
2194
2195 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2196   ElementsKind elements_kind = instr->elements_kind();
2197
2198   if ((kPointerSize == kInt64Size) && instr->IsDehoisted()) {
2199     FindDehoistedKeyDefinitions(instr->key());
2200   }
2201
2202   if (!instr->is_typed_elements()) {
2203     ASSERT(instr->elements()->representation().IsTagged());
2204     bool needs_write_barrier = instr->NeedsWriteBarrier();
2205     LOperand* object = NULL;
2206     LOperand* key = NULL;
2207     LOperand* val = NULL;
2208
2209     Representation value_representation = instr->value()->representation();
2210     if (value_representation.IsDouble()) {
2211       object = UseRegisterAtStart(instr->elements());
2212       val = UseRegisterAtStart(instr->value());
2213       key = UseRegisterOrConstantAtStart(instr->key());
2214     } else {
2215       ASSERT(value_representation.IsSmiOrTagged() ||
2216              value_representation.IsInteger32());
2217       if (needs_write_barrier) {
2218         object = UseTempRegister(instr->elements());
2219         val = UseTempRegister(instr->value());
2220         key = UseTempRegister(instr->key());
2221       } else {
2222         object = UseRegisterAtStart(instr->elements());
2223         val = UseRegisterOrConstantAtStart(instr->value());
2224         key = UseRegisterOrConstantAtStart(instr->key());
2225       }
2226     }
2227
2228     return new(zone()) LStoreKeyed(object, key, val);
2229   }
2230
2231   ASSERT(
2232        (instr->value()->representation().IsInteger32() &&
2233        !IsDoubleOrFloatElementsKind(elements_kind)) ||
2234        (instr->value()->representation().IsDouble() &&
2235        IsDoubleOrFloatElementsKind(elements_kind)));
2236   ASSERT((instr->is_fixed_typed_array() &&
2237           instr->elements()->representation().IsTagged()) ||
2238          (instr->is_external() &&
2239           instr->elements()->representation().IsExternal()));
2240   bool val_is_temp_register =
2241       elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
2242       elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
2243       elements_kind == FLOAT32_ELEMENTS;
2244   LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
2245       : UseRegister(instr->value());
2246   LOperand* key = NULL;
2247   if (kPointerSize == kInt64Size) {
2248     key = UseRegisterOrConstantAtStart(instr->key());
2249   } else {
2250     bool clobbers_key = ExternalArrayOpRequiresTemp(
2251         instr->key()->representation(), elements_kind);
2252     key = clobbers_key
2253         ? UseTempRegister(instr->key())
2254         : UseRegisterOrConstantAtStart(instr->key());
2255   }
2256   LOperand* backing_store = UseRegister(instr->elements());
2257   return new(zone()) LStoreKeyed(backing_store, key, val);
2258 }
2259
2260
2261 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2262   LOperand* context = UseFixed(instr->context(), rsi);
2263   LOperand* object = UseFixed(instr->object(), rdx);
2264   LOperand* key = UseFixed(instr->key(), rcx);
2265   LOperand* value = UseFixed(instr->value(), rax);
2266
2267   ASSERT(instr->object()->representation().IsTagged());
2268   ASSERT(instr->key()->representation().IsTagged());
2269   ASSERT(instr->value()->representation().IsTagged());
2270
2271   LStoreKeyedGeneric* result =
2272       new(zone()) LStoreKeyedGeneric(context, object, key, value);
2273   return MarkAsCall(result, instr);
2274 }
2275
2276
2277 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2278     HTransitionElementsKind* instr) {
2279   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
2280     LOperand* object = UseRegister(instr->object());
2281     LOperand* new_map_reg = TempRegister();
2282     LOperand* temp_reg = TempRegister();
2283     LTransitionElementsKind* result = new(zone()) LTransitionElementsKind(
2284         object, NULL, new_map_reg, temp_reg);
2285     return result;
2286   } else {
2287     LOperand* object = UseFixed(instr->object(), rax);
2288     LOperand* context = UseFixed(instr->context(), rsi);
2289     LTransitionElementsKind* result =
2290         new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
2291     return MarkAsCall(result, instr);
2292   }
2293 }
2294
2295
2296 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2297     HTrapAllocationMemento* instr) {
2298   LOperand* object = UseRegister(instr->object());
2299   LOperand* temp = TempRegister();
2300   LTrapAllocationMemento* result =
2301       new(zone()) LTrapAllocationMemento(object, temp);
2302   return AssignEnvironment(result);
2303 }
2304
2305
2306 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2307   bool is_in_object = instr->access().IsInobject();
2308   bool is_external_location = instr->access().IsExternalMemory() &&
2309       instr->access().offset() == 0;
2310   bool needs_write_barrier = instr->NeedsWriteBarrier();
2311   bool needs_write_barrier_for_map = instr->has_transition() &&
2312       instr->NeedsWriteBarrierForMap();
2313
2314   LOperand* obj;
2315   if (needs_write_barrier) {
2316     obj = is_in_object
2317         ? UseRegister(instr->object())
2318         : UseTempRegister(instr->object());
2319   } else if (is_external_location) {
2320     ASSERT(!is_in_object);
2321     ASSERT(!needs_write_barrier);
2322     ASSERT(!needs_write_barrier_for_map);
2323     obj = UseRegisterOrConstant(instr->object());
2324   } else {
2325     obj = needs_write_barrier_for_map
2326         ? UseRegister(instr->object())
2327         : UseRegisterAtStart(instr->object());
2328   }
2329
2330   bool can_be_constant = instr->value()->IsConstant() &&
2331       HConstant::cast(instr->value())->NotInNewSpace() &&
2332       !instr->field_representation().IsDouble();
2333
2334   LOperand* val;
2335   if (needs_write_barrier) {
2336     val = UseTempRegister(instr->value());
2337   } else if (is_external_location) {
2338     val = UseFixed(instr->value(), rax);
2339   } else if (can_be_constant) {
2340     val = UseRegisterOrConstant(instr->value());
2341   } else if (instr->field_representation().IsSmi()) {
2342     val = UseRegister(instr->value());
2343   } else if (instr->field_representation().IsDouble()) {
2344     val = UseRegisterAtStart(instr->value());
2345   } else {
2346     val = UseRegister(instr->value());
2347   }
2348
2349   // We only need a scratch register if we have a write barrier or we
2350   // have a store into the properties array (not in-object-property).
2351   LOperand* temp = (!is_in_object || needs_write_barrier ||
2352       needs_write_barrier_for_map) ? TempRegister() : NULL;
2353
2354   return new(zone()) LStoreNamedField(obj, val, temp);
2355 }
2356
2357
2358 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2359   LOperand* context = UseFixed(instr->context(), rsi);
2360   LOperand* object = UseFixed(instr->object(), rdx);
2361   LOperand* value = UseFixed(instr->value(), rax);
2362
2363   LStoreNamedGeneric* result =
2364       new(zone()) LStoreNamedGeneric(context, object, value);
2365   return MarkAsCall(result, instr);
2366 }
2367
2368
2369 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2370   LOperand* context = UseFixed(instr->context(), rsi);
2371   LOperand* left = UseFixed(instr->left(), rdx);
2372   LOperand* right = UseFixed(instr->right(), rax);
2373   return MarkAsCall(
2374       DefineFixed(new(zone()) LStringAdd(context, left, right), rax), instr);
2375 }
2376
2377
2378 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2379   LOperand* string = UseTempRegister(instr->string());
2380   LOperand* index = UseTempRegister(instr->index());
2381   LOperand* context = UseAny(instr->context());
2382   LStringCharCodeAt* result =
2383       new(zone()) LStringCharCodeAt(context, string, index);
2384   return AssignPointerMap(DefineAsRegister(result));
2385 }
2386
2387
2388 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2389   LOperand* char_code = UseRegister(instr->value());
2390   LOperand* context = UseAny(instr->context());
2391   LStringCharFromCode* result =
2392       new(zone()) LStringCharFromCode(context, char_code);
2393   return AssignPointerMap(DefineAsRegister(result));
2394 }
2395
2396
2397 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2398   info()->MarkAsDeferredCalling();
2399   LOperand* context = UseAny(instr->context());
2400   LOperand* size = instr->size()->IsConstant()
2401       ? UseConstant(instr->size())
2402       : UseTempRegister(instr->size());
2403   LOperand* temp = TempRegister();
2404   LAllocate* result = new(zone()) LAllocate(context, size, temp);
2405   return AssignPointerMap(DefineAsRegister(result));
2406 }
2407
2408
2409 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2410   LOperand* context = UseFixed(instr->context(), rsi);
2411   LRegExpLiteral* result = new(zone()) LRegExpLiteral(context);
2412   return MarkAsCall(DefineFixed(result, rax), instr);
2413 }
2414
2415
2416 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2417   LOperand* context = UseFixed(instr->context(), rsi);
2418   LFunctionLiteral* result = new(zone()) LFunctionLiteral(context);
2419   return MarkAsCall(DefineFixed(result, rax), instr);
2420 }
2421
2422
2423 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2424   ASSERT(argument_count_ == 0);
2425   allocator_->MarkAsOsrEntry();
2426   current_block_->last_environment()->set_ast_id(instr->ast_id());
2427   return AssignEnvironment(new(zone()) LOsrEntry);
2428 }
2429
2430
2431 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2432   LParameter* result = new(zone()) LParameter;
2433   if (instr->kind() == HParameter::STACK_PARAMETER) {
2434     int spill_index = chunk()->GetParameterStackSlot(instr->index());
2435     return DefineAsSpilled(result, spill_index);
2436   } else {
2437     ASSERT(info()->IsStub());
2438     CodeStubInterfaceDescriptor* descriptor =
2439         info()->code_stub()->GetInterfaceDescriptor();
2440     int index = static_cast<int>(instr->index());
2441     Register reg = descriptor->GetParameterRegister(index);
2442     return DefineFixed(result, reg);
2443   }
2444 }
2445
2446
2447 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2448   // Use an index that corresponds to the location in the unoptimized frame,
2449   // which the optimized frame will subsume.
2450   int env_index = instr->index();
2451   int spill_index = 0;
2452   if (instr->environment()->is_parameter_index(env_index)) {
2453     spill_index = chunk()->GetParameterStackSlot(env_index);
2454   } else {
2455     spill_index = env_index - instr->environment()->first_local_index();
2456     if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
2457       Abort(kTooManySpillSlotsNeededForOSR);
2458       spill_index = 0;
2459     }
2460   }
2461   return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
2462 }
2463
2464
2465 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2466   LOperand* context = UseFixed(instr->context(), rsi);
2467   LCallStub* result = new(zone()) LCallStub(context);
2468   return MarkAsCall(DefineFixed(result, rax), instr);
2469 }
2470
2471
2472 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2473   // There are no real uses of the arguments object.
2474   // arguments.length and element access are supported directly on
2475   // stack arguments, and any real arguments object use causes a bailout.
2476   // So this value is never used.
2477   return NULL;
2478 }
2479
2480
2481 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2482   instr->ReplayEnvironment(current_block_->last_environment());
2483
2484   // There are no real uses of a captured object.
2485   return NULL;
2486 }
2487
2488
2489 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2490   info()->MarkAsRequiresFrame();
2491   LOperand* args = UseRegister(instr->arguments());
2492   LOperand* length;
2493   LOperand* index;
2494   if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2495     length = UseRegisterOrConstant(instr->length());
2496     index = UseOrConstant(instr->index());
2497   } else {
2498     length = UseTempRegister(instr->length());
2499     index = Use(instr->index());
2500   }
2501   return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
2502 }
2503
2504
2505 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2506   LOperand* object = UseFixed(instr->value(), rax);
2507   LToFastProperties* result = new(zone()) LToFastProperties(object);
2508   return MarkAsCall(DefineFixed(result, rax), instr);
2509 }
2510
2511
2512 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2513   LOperand* context = UseFixed(instr->context(), rsi);
2514   LOperand* value = UseAtStart(instr->value());
2515   LTypeof* result = new(zone()) LTypeof(context, value);
2516   return MarkAsCall(DefineFixed(result, rax), instr);
2517 }
2518
2519
2520 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2521   return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2522 }
2523
2524
2525 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2526     HIsConstructCallAndBranch* instr) {
2527   return new(zone()) LIsConstructCallAndBranch(TempRegister());
2528 }
2529
2530
2531 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2532   instr->ReplayEnvironment(current_block_->last_environment());
2533   return NULL;
2534 }
2535
2536
2537 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2538   info()->MarkAsDeferredCalling();
2539   if (instr->is_function_entry()) {
2540     LOperand* context = UseFixed(instr->context(), rsi);
2541     return MarkAsCall(new(zone()) LStackCheck(context), instr);
2542   } else {
2543     ASSERT(instr->is_backwards_branch());
2544     LOperand* context = UseAny(instr->context());
2545     return AssignEnvironment(
2546         AssignPointerMap(new(zone()) LStackCheck(context)));
2547   }
2548 }
2549
2550
2551 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2552   HEnvironment* outer = current_block_->last_environment();
2553   outer->set_ast_id(instr->ReturnId());
2554   HConstant* undefined = graph()->GetConstantUndefined();
2555   HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2556                                                instr->arguments_count(),
2557                                                instr->function(),
2558                                                undefined,
2559                                                instr->inlining_kind());
2560   // Only replay binding of arguments object if it wasn't removed from graph.
2561   if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
2562     inner->Bind(instr->arguments_var(), instr->arguments_object());
2563   }
2564   inner->set_entry(instr);
2565   current_block_->UpdateEnvironment(inner);
2566   chunk_->AddInlinedClosure(instr->closure());
2567   return NULL;
2568 }
2569
2570
2571 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2572   LInstruction* pop = NULL;
2573
2574   HEnvironment* env = current_block_->last_environment();
2575
2576   if (env->entry()->arguments_pushed()) {
2577     int argument_count = env->arguments_environment()->parameter_count();
2578     pop = new(zone()) LDrop(argument_count);
2579     ASSERT(instr->argument_delta() == -argument_count);
2580   }
2581
2582   HEnvironment* outer = current_block_->last_environment()->
2583       DiscardInlined(false);
2584   current_block_->UpdateEnvironment(outer);
2585
2586   return pop;
2587 }
2588
2589
2590 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2591   LOperand* context = UseFixed(instr->context(), rsi);
2592   LOperand* object = UseFixed(instr->enumerable(), rax);
2593   LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
2594   return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
2595 }
2596
2597
2598 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2599   LOperand* map = UseRegister(instr->map());
2600   return AssignEnvironment(DefineAsRegister(
2601       new(zone()) LForInCacheArray(map)));
2602 }
2603
2604
2605 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2606   LOperand* value = UseRegisterAtStart(instr->value());
2607   LOperand* map = UseRegisterAtStart(instr->map());
2608   return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
2609 }
2610
2611
2612 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2613   LOperand* object = UseRegister(instr->object());
2614   LOperand* index = UseTempRegister(instr->index());
2615   LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index);
2616   LInstruction* result = DefineSameAsFirst(load);
2617   return AssignPointerMap(result);
2618 }
2619
2620
2621 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) {
2622   LOperand* context = UseRegisterAtStart(instr->context());
2623   return new(zone()) LStoreFrameContext(context);
2624 }
2625
2626
2627 LInstruction* LChunkBuilder::DoAllocateBlockContext(
2628     HAllocateBlockContext* instr) {
2629   LOperand* context = UseFixed(instr->context(), rsi);
2630   LOperand* function = UseRegisterAtStart(instr->function());
2631   LAllocateBlockContext* result =
2632       new(zone()) LAllocateBlockContext(context, function);
2633   return MarkAsCall(DefineFixed(result, rsi), instr);
2634 }
2635
2636
2637 } }  // namespace v8::internal
2638
2639 #endif  // V8_TARGET_ARCH_X64