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