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