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