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