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