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