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