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