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