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