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