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