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