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