• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/crankshaft/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 CpuFeatures::IsSupported(VECTOR_FACILITY)
623                ? DefineAsRegister(result)
624                : DefineSameAsFirst(result);
625   }
626 }
627 
DoArithmeticT(Token::Value op,HBinaryOperation * instr)628 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
629                                            HBinaryOperation* instr) {
630   HValue* left = instr->left();
631   HValue* right = instr->right();
632   DCHECK(left->representation().IsTagged());
633   DCHECK(right->representation().IsTagged());
634   LOperand* context = UseFixed(instr->context(), cp);
635   LOperand* left_operand = UseFixed(left, r3);
636   LOperand* right_operand = UseFixed(right, r2);
637   LArithmeticT* result =
638       new (zone()) LArithmeticT(op, context, left_operand, right_operand);
639   return MarkAsCall(DefineFixed(result, r2), instr);
640 }
641 
DoBasicBlock(HBasicBlock * block,HBasicBlock * next_block)642 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
643   DCHECK(is_building());
644   current_block_ = block;
645   next_block_ = next_block;
646   if (block->IsStartBlock()) {
647     block->UpdateEnvironment(graph_->start_environment());
648     argument_count_ = 0;
649   } else if (block->predecessors()->length() == 1) {
650     // We have a single predecessor => copy environment and outgoing
651     // argument count from the predecessor.
652     DCHECK(block->phis()->length() == 0);
653     HBasicBlock* pred = block->predecessors()->at(0);
654     HEnvironment* last_environment = pred->last_environment();
655     DCHECK(last_environment != NULL);
656     // Only copy the environment, if it is later used again.
657     if (pred->end()->SecondSuccessor() == NULL) {
658       DCHECK(pred->end()->FirstSuccessor() == block);
659     } else {
660       if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
661           pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
662         last_environment = last_environment->Copy();
663       }
664     }
665     block->UpdateEnvironment(last_environment);
666     DCHECK(pred->argument_count() >= 0);
667     argument_count_ = pred->argument_count();
668   } else {
669     // We are at a state join => process phis.
670     HBasicBlock* pred = block->predecessors()->at(0);
671     // No need to copy the environment, it cannot be used later.
672     HEnvironment* last_environment = pred->last_environment();
673     for (int i = 0; i < block->phis()->length(); ++i) {
674       HPhi* phi = block->phis()->at(i);
675       if (phi->HasMergedIndex()) {
676         last_environment->SetValueAt(phi->merged_index(), phi);
677       }
678     }
679     for (int i = 0; i < block->deleted_phis()->length(); ++i) {
680       if (block->deleted_phis()->at(i) < last_environment->length()) {
681         last_environment->SetValueAt(block->deleted_phis()->at(i),
682                                      graph_->GetConstantUndefined());
683       }
684     }
685     block->UpdateEnvironment(last_environment);
686     // Pick up the outgoing argument count of one of the predecessors.
687     argument_count_ = pred->argument_count();
688   }
689   HInstruction* current = block->first();
690   int start = chunk_->instructions()->length();
691   while (current != NULL && !is_aborted()) {
692     // Code for constants in registers is generated lazily.
693     if (!current->EmitAtUses()) {
694       VisitInstruction(current);
695     }
696     current = current->next();
697   }
698   int end = chunk_->instructions()->length() - 1;
699   if (end >= start) {
700     block->set_first_instruction_index(start);
701     block->set_last_instruction_index(end);
702   }
703   block->set_argument_count(argument_count_);
704   next_block_ = NULL;
705   current_block_ = NULL;
706 }
707 
VisitInstruction(HInstruction * current)708 void LChunkBuilder::VisitInstruction(HInstruction* current) {
709   HInstruction* old_current = current_instruction_;
710   current_instruction_ = current;
711 
712   LInstruction* instr = NULL;
713   if (current->CanReplaceWithDummyUses()) {
714     if (current->OperandCount() == 0) {
715       instr = DefineAsRegister(new (zone()) LDummy());
716     } else {
717       DCHECK(!current->OperandAt(0)->IsControlInstruction());
718       instr = DefineAsRegister(new (zone())
719                                    LDummyUse(UseAny(current->OperandAt(0))));
720     }
721     for (int i = 1; i < current->OperandCount(); ++i) {
722       if (current->OperandAt(i)->IsControlInstruction()) continue;
723       LInstruction* dummy =
724           new (zone()) LDummyUse(UseAny(current->OperandAt(i)));
725       dummy->set_hydrogen_value(current);
726       chunk_->AddInstruction(dummy, current_block_);
727     }
728   } else {
729     HBasicBlock* successor;
730     if (current->IsControlInstruction() &&
731         HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) &&
732         successor != NULL) {
733       instr = new (zone()) LGoto(successor);
734     } else {
735       instr = current->CompileToLithium(this);
736     }
737   }
738 
739   argument_count_ += current->argument_delta();
740   DCHECK(argument_count_ >= 0);
741 
742   if (instr != NULL) {
743     AddInstruction(instr, current);
744   }
745 
746   current_instruction_ = old_current;
747 }
748 
AddInstruction(LInstruction * instr,HInstruction * hydrogen_val)749 void LChunkBuilder::AddInstruction(LInstruction* instr,
750                                    HInstruction* hydrogen_val) {
751   // Associate the hydrogen instruction first, since we may need it for
752   // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
753   instr->set_hydrogen_value(hydrogen_val);
754 
755 #if DEBUG
756   // Make sure that the lithium instruction has either no fixed register
757   // constraints in temps or the result OR no uses that are only used at
758   // start. If this invariant doesn't hold, the register allocator can decide
759   // to insert a split of a range immediately before the instruction due to an
760   // already allocated register needing to be used for the instruction's fixed
761   // register constraint. In this case, The register allocator won't see an
762   // interference between the split child and the use-at-start (it would if
763   // the it was just a plain use), so it is free to move the split child into
764   // the same register that is used for the use-at-start.
765   // See https://code.google.com/p/chromium/issues/detail?id=201590
766   if (!(instr->ClobbersRegisters() &&
767         instr->ClobbersDoubleRegisters(isolate()))) {
768     int fixed = 0;
769     int used_at_start = 0;
770     for (UseIterator it(instr); !it.Done(); it.Advance()) {
771       LUnallocated* operand = LUnallocated::cast(it.Current());
772       if (operand->IsUsedAtStart()) ++used_at_start;
773     }
774     if (instr->Output() != NULL) {
775       if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
776     }
777     for (TempIterator it(instr); !it.Done(); it.Advance()) {
778       LUnallocated* operand = LUnallocated::cast(it.Current());
779       if (operand->HasFixedPolicy()) ++fixed;
780     }
781     DCHECK(fixed == 0 || used_at_start == 0);
782   }
783 #endif
784 
785   if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
786     instr = AssignPointerMap(instr);
787   }
788   if (FLAG_stress_environments && !instr->HasEnvironment()) {
789     instr = AssignEnvironment(instr);
790   }
791   chunk_->AddInstruction(instr, current_block_);
792 
793   CreateLazyBailoutForCall(current_block_, instr, hydrogen_val);
794 }
795 
DoPrologue(HPrologue * instr)796 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
797   LInstruction* result = new (zone()) LPrologue();
798   if (info_->scope()->NeedsContext()) {
799     result = MarkAsCall(result, instr);
800   }
801   return result;
802 }
803 
DoGoto(HGoto * instr)804 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
805   return new (zone()) LGoto(instr->FirstSuccessor());
806 }
807 
DoBranch(HBranch * instr)808 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
809   HValue* value = instr->value();
810   Representation r = value->representation();
811   HType type = value->type();
812   ToBooleanHints expected = instr->expected_input_types();
813   if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny;
814 
815   bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
816                    type.IsJSArray() || type.IsHeapNumber() || type.IsString();
817   LInstruction* branch = new (zone()) LBranch(UseRegister(value));
818   if (!easy_case && ((!(expected & ToBooleanHint::kSmallInteger) &&
819                       (expected & ToBooleanHint::kNeedsMap)) ||
820                      expected != ToBooleanHint::kAny)) {
821     branch = AssignEnvironment(branch);
822   }
823   return branch;
824 }
825 
DoDebugBreak(HDebugBreak * instr)826 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
827   return new (zone()) LDebugBreak();
828 }
829 
DoCompareMap(HCompareMap * instr)830 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
831   DCHECK(instr->value()->representation().IsTagged());
832   LOperand* value = UseRegister(instr->value());
833   LOperand* temp = TempRegister();
834   return new (zone()) LCmpMapAndBranch(value, temp);
835 }
836 
DoArgumentsLength(HArgumentsLength * instr)837 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
838   info()->MarkAsRequiresFrame();
839   LOperand* value = UseRegister(instr->value());
840   return DefineAsRegister(new (zone()) LArgumentsLength(value));
841 }
842 
DoArgumentsElements(HArgumentsElements * elems)843 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
844   info()->MarkAsRequiresFrame();
845   return DefineAsRegister(new (zone()) LArgumentsElements);
846 }
847 
DoHasInPrototypeChainAndBranch(HHasInPrototypeChainAndBranch * instr)848 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
849     HHasInPrototypeChainAndBranch* instr) {
850   LOperand* object = UseRegister(instr->object());
851   LOperand* prototype = UseRegister(instr->prototype());
852   LHasInPrototypeChainAndBranch* result =
853       new (zone()) LHasInPrototypeChainAndBranch(object, prototype);
854   return AssignEnvironment(result);
855 }
856 
DoWrapReceiver(HWrapReceiver * instr)857 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
858   LOperand* receiver = UseRegisterAtStart(instr->receiver());
859   LOperand* function = UseRegisterAtStart(instr->function());
860   LWrapReceiver* result = new (zone()) LWrapReceiver(receiver, function);
861   return AssignEnvironment(DefineAsRegister(result));
862 }
863 
DoApplyArguments(HApplyArguments * instr)864 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
865   LOperand* function = UseFixed(instr->function(), r3);
866   LOperand* receiver = UseFixed(instr->receiver(), r2);
867   LOperand* length = UseFixed(instr->length(), r4);
868   LOperand* elements = UseFixed(instr->elements(), r5);
869   LApplyArguments* result =
870       new (zone()) LApplyArguments(function, receiver, length, elements);
871   return MarkAsCall(DefineFixed(result, r2), instr, CAN_DEOPTIMIZE_EAGERLY);
872 }
873 
DoPushArguments(HPushArguments * instr)874 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
875   int argc = instr->OperandCount();
876   for (int i = 0; i < argc; ++i) {
877     LOperand* argument = Use(instr->argument(i));
878     AddInstruction(new (zone()) LPushArgument(argument), instr);
879   }
880   return NULL;
881 }
882 
DoStoreCodeEntry(HStoreCodeEntry * store_code_entry)883 LInstruction* LChunkBuilder::DoStoreCodeEntry(
884     HStoreCodeEntry* store_code_entry) {
885   LOperand* function = UseRegister(store_code_entry->function());
886   LOperand* code_object = UseTempRegister(store_code_entry->code_object());
887   return new (zone()) LStoreCodeEntry(function, code_object);
888 }
889 
DoInnerAllocatedObject(HInnerAllocatedObject * instr)890 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
891     HInnerAllocatedObject* instr) {
892   LOperand* base_object = UseRegisterAtStart(instr->base_object());
893   LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
894   return DefineAsRegister(new (zone())
895                               LInnerAllocatedObject(base_object, offset));
896 }
897 
DoThisFunction(HThisFunction * instr)898 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
899   return instr->HasNoUses() ? NULL
900                             : DefineAsRegister(new (zone()) LThisFunction);
901 }
902 
DoContext(HContext * instr)903 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
904   if (instr->HasNoUses()) return NULL;
905 
906   if (info()->IsStub()) {
907     return DefineFixed(new (zone()) LContext, cp);
908   }
909 
910   return DefineAsRegister(new (zone()) LContext);
911 }
912 
DoDeclareGlobals(HDeclareGlobals * instr)913 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
914   LOperand* context = UseFixed(instr->context(), cp);
915   return MarkAsCall(new (zone()) LDeclareGlobals(context), instr);
916 }
917 
DoCallWithDescriptor(HCallWithDescriptor * instr)918 LInstruction* LChunkBuilder::DoCallWithDescriptor(HCallWithDescriptor* instr) {
919   CallInterfaceDescriptor descriptor = instr->descriptor();
920   DCHECK_EQ(descriptor.GetParameterCount() +
921                 LCallWithDescriptor::kImplicitRegisterParameterCount,
922             instr->OperandCount());
923 
924   LOperand* target = UseRegisterOrConstantAtStart(instr->target());
925   ZoneList<LOperand*> ops(instr->OperandCount(), zone());
926   // Target
927   ops.Add(target, zone());
928   // Context
929   LOperand* op = UseFixed(instr->OperandAt(1), cp);
930   ops.Add(op, zone());
931   // Load register parameters.
932   int i = 0;
933   for (; i < descriptor.GetRegisterParameterCount(); i++) {
934     op = UseFixed(instr->OperandAt(
935                       i + LCallWithDescriptor::kImplicitRegisterParameterCount),
936                   descriptor.GetRegisterParameter(i));
937     ops.Add(op, zone());
938   }
939   // Push stack parameters.
940   for (; i < descriptor.GetParameterCount(); i++) {
941     op = UseAny(instr->OperandAt(
942         i + LCallWithDescriptor::kImplicitRegisterParameterCount));
943     AddInstruction(new (zone()) LPushArgument(op), instr);
944   }
945 
946   LCallWithDescriptor* result =
947       new (zone()) LCallWithDescriptor(descriptor, ops, zone());
948   if (instr->syntactic_tail_call_mode() == TailCallMode::kAllow) {
949     result->MarkAsSyntacticTailCall();
950   }
951   return MarkAsCall(DefineFixed(result, r2), instr);
952 }
953 
DoInvokeFunction(HInvokeFunction * instr)954 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
955   LOperand* context = UseFixed(instr->context(), cp);
956   LOperand* function = UseFixed(instr->function(), r3);
957   LInvokeFunction* result = new (zone()) LInvokeFunction(context, function);
958   if (instr->syntactic_tail_call_mode() == TailCallMode::kAllow) {
959     result->MarkAsSyntacticTailCall();
960   }
961   return MarkAsCall(DefineFixed(result, r2), instr, CANNOT_DEOPTIMIZE_EAGERLY);
962 }
963 
DoUnaryMathOperation(HUnaryMathOperation * instr)964 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
965   switch (instr->op()) {
966     case kMathFloor:
967       return DoMathFloor(instr);
968     case kMathRound:
969       return DoMathRound(instr);
970     case kMathFround:
971       return DoMathFround(instr);
972     case kMathAbs:
973       return DoMathAbs(instr);
974     case kMathLog:
975       return DoMathLog(instr);
976     case kMathCos:
977       return DoMathCos(instr);
978     case kMathSin:
979       return DoMathSin(instr);
980     case kMathExp:
981       return DoMathExp(instr);
982     case kMathSqrt:
983       return DoMathSqrt(instr);
984     case kMathPowHalf:
985       return DoMathPowHalf(instr);
986     case kMathClz32:
987       return DoMathClz32(instr);
988     default:
989       UNREACHABLE();
990       return NULL;
991   }
992 }
993 
DoMathFloor(HUnaryMathOperation * instr)994 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
995   LOperand* input = UseRegister(instr->value());
996   LMathFloor* result = new (zone()) LMathFloor(input);
997   return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
998 }
999 
DoMathRound(HUnaryMathOperation * instr)1000 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1001   LOperand* input = UseRegister(instr->value());
1002   LOperand* temp = TempDoubleRegister();
1003   LMathRound* result = new (zone()) LMathRound(input, temp);
1004   return AssignEnvironment(DefineAsRegister(result));
1005 }
1006 
DoMathFround(HUnaryMathOperation * instr)1007 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
1008   LOperand* input = UseRegister(instr->value());
1009   LMathFround* result = new (zone()) LMathFround(input);
1010   return DefineAsRegister(result);
1011 }
1012 
DoMathAbs(HUnaryMathOperation * instr)1013 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1014   Representation r = instr->value()->representation();
1015   LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32())
1016                           ? NULL
1017                           : UseFixed(instr->context(), cp);
1018   LOperand* input = UseRegister(instr->value());
1019   LInstruction* result =
1020       DefineAsRegister(new (zone()) LMathAbs(context, input));
1021   if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1022   if (!r.IsDouble()) result = AssignEnvironment(result);
1023   return result;
1024 }
1025 
DoMathLog(HUnaryMathOperation * instr)1026 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1027   DCHECK(instr->representation().IsDouble());
1028   DCHECK(instr->value()->representation().IsDouble());
1029   LOperand* input = UseFixedDouble(instr->value(), d0);
1030   return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d0), instr);
1031 }
1032 
DoMathClz32(HUnaryMathOperation * instr)1033 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1034   LOperand* input = UseRegisterAtStart(instr->value());
1035   LMathClz32* result = new (zone()) LMathClz32(input);
1036   return DefineAsRegister(result);
1037 }
1038 
DoMathCos(HUnaryMathOperation * instr)1039 LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
1040   DCHECK(instr->representation().IsDouble());
1041   DCHECK(instr->value()->representation().IsDouble());
1042   LOperand* input = UseFixedDouble(instr->value(), d0);
1043   return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), d0), instr);
1044 }
1045 
DoMathSin(HUnaryMathOperation * instr)1046 LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
1047   DCHECK(instr->representation().IsDouble());
1048   DCHECK(instr->value()->representation().IsDouble());
1049   LOperand* input = UseFixedDouble(instr->value(), d0);
1050   return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), d0), instr);
1051 }
1052 
DoMathExp(HUnaryMathOperation * instr)1053 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1054   DCHECK(instr->representation().IsDouble());
1055   DCHECK(instr->value()->representation().IsDouble());
1056   LOperand* input = UseFixedDouble(instr->value(), d0);
1057   return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), d0), instr);
1058 }
1059 
DoMathSqrt(HUnaryMathOperation * instr)1060 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1061   LOperand* input = UseAtStart(instr->value());
1062   LMathSqrt* result = new (zone()) LMathSqrt(input);
1063   return DefineAsRegister(result);
1064 }
1065 
DoMathPowHalf(HUnaryMathOperation * instr)1066 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1067   LOperand* input = UseRegisterAtStart(instr->value());
1068   LMathPowHalf* result = new (zone()) LMathPowHalf(input);
1069   return DefineAsRegister(result);
1070 }
1071 
DoCallNewArray(HCallNewArray * instr)1072 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1073   LOperand* context = UseFixed(instr->context(), cp);
1074   LOperand* constructor = UseFixed(instr->constructor(), r3);
1075   LCallNewArray* result = new (zone()) LCallNewArray(context, constructor);
1076   return MarkAsCall(DefineFixed(result, r2), instr);
1077 }
1078 
DoCallRuntime(HCallRuntime * instr)1079 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1080   LOperand* context = UseFixed(instr->context(), cp);
1081   return MarkAsCall(DefineFixed(new (zone()) LCallRuntime(context), r2), instr);
1082 }
1083 
DoRor(HRor * instr)1084 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1085   return DoShift(Token::ROR, instr);
1086 }
1087 
DoShr(HShr * instr)1088 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1089   return DoShift(Token::SHR, instr);
1090 }
1091 
DoSar(HSar * instr)1092 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1093   return DoShift(Token::SAR, instr);
1094 }
1095 
DoShl(HShl * instr)1096 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1097   return DoShift(Token::SHL, instr);
1098 }
1099 
DoBitwise(HBitwise * instr)1100 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1101   if (instr->representation().IsSmiOrInteger32()) {
1102     DCHECK(instr->left()->representation().Equals(instr->representation()));
1103     DCHECK(instr->right()->representation().Equals(instr->representation()));
1104     DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32));
1105 
1106     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1107     LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1108     return DefineAsRegister(new (zone()) LBitI(left, right));
1109   } else {
1110     return DoArithmeticT(instr->op(), instr);
1111   }
1112 }
1113 
DoDivByPowerOf2I(HDiv * instr)1114 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1115   DCHECK(instr->representation().IsSmiOrInteger32());
1116   DCHECK(instr->left()->representation().Equals(instr->representation()));
1117   DCHECK(instr->right()->representation().Equals(instr->representation()));
1118   LOperand* dividend = UseRegister(instr->left());
1119   int32_t divisor = instr->right()->GetInteger32Constant();
1120   LInstruction* result =
1121       DefineAsRegister(new (zone()) LDivByPowerOf2I(dividend, divisor));
1122   if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1123       (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
1124       (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1125        divisor != 1 && divisor != -1)) {
1126     result = AssignEnvironment(result);
1127   }
1128   return result;
1129 }
1130 
DoDivByConstI(HDiv * instr)1131 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1132   DCHECK(instr->representation().IsInteger32());
1133   DCHECK(instr->left()->representation().Equals(instr->representation()));
1134   DCHECK(instr->right()->representation().Equals(instr->representation()));
1135   LOperand* dividend = UseRegister(instr->left());
1136   int32_t divisor = instr->right()->GetInteger32Constant();
1137   LInstruction* result =
1138       DefineAsRegister(new (zone()) LDivByConstI(dividend, divisor));
1139   if (divisor == 0 ||
1140       (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1141       !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1142     result = AssignEnvironment(result);
1143   }
1144   return result;
1145 }
1146 
DoDivI(HDiv * instr)1147 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
1148   DCHECK(instr->representation().IsSmiOrInteger32());
1149   DCHECK(instr->left()->representation().Equals(instr->representation()));
1150   DCHECK(instr->right()->representation().Equals(instr->representation()));
1151   LOperand* dividend = UseRegister(instr->left());
1152   LOperand* divisor = UseRegister(instr->right());
1153   LInstruction* result =
1154       DefineAsRegister(new (zone()) LDivI(dividend, divisor));
1155   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1156       instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1157       (instr->CheckFlag(HValue::kCanOverflow) &&
1158        !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) ||
1159       (!instr->IsMathFloorOfDiv() &&
1160        !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1161     result = AssignEnvironment(result);
1162   }
1163   return result;
1164 }
1165 
DoDiv(HDiv * instr)1166 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1167   if (instr->representation().IsSmiOrInteger32()) {
1168     if (instr->RightIsPowerOf2()) {
1169       return DoDivByPowerOf2I(instr);
1170     } else if (instr->right()->IsConstant()) {
1171       return DoDivByConstI(instr);
1172     } else {
1173       return DoDivI(instr);
1174     }
1175   } else if (instr->representation().IsDouble()) {
1176     return DoArithmeticD(Token::DIV, instr);
1177   } else {
1178     return DoArithmeticT(Token::DIV, instr);
1179   }
1180 }
1181 
DoFlooringDivByPowerOf2I(HMathFloorOfDiv * instr)1182 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1183   LOperand* dividend = UseRegisterAtStart(instr->left());
1184   int32_t divisor = instr->right()->GetInteger32Constant();
1185   LInstruction* result =
1186       DefineAsRegister(new (zone()) LFlooringDivByPowerOf2I(dividend, divisor));
1187   if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1188       (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
1189     result = AssignEnvironment(result);
1190   }
1191   return result;
1192 }
1193 
DoFlooringDivByConstI(HMathFloorOfDiv * instr)1194 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1195   DCHECK(instr->representation().IsInteger32());
1196   DCHECK(instr->left()->representation().Equals(instr->representation()));
1197   DCHECK(instr->right()->representation().Equals(instr->representation()));
1198   LOperand* dividend = UseRegister(instr->left());
1199   int32_t divisor = instr->right()->GetInteger32Constant();
1200   LOperand* temp =
1201       ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
1202        (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive)))
1203           ? NULL
1204           : TempRegister();
1205   LInstruction* result = DefineAsRegister(
1206       new (zone()) LFlooringDivByConstI(dividend, divisor, temp));
1207   if (divisor == 0 ||
1208       (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
1209     result = AssignEnvironment(result);
1210   }
1211   return result;
1212 }
1213 
DoFlooringDivI(HMathFloorOfDiv * instr)1214 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1215   DCHECK(instr->representation().IsSmiOrInteger32());
1216   DCHECK(instr->left()->representation().Equals(instr->representation()));
1217   DCHECK(instr->right()->representation().Equals(instr->representation()));
1218   LOperand* dividend = UseRegister(instr->left());
1219   LOperand* divisor = UseRegister(instr->right());
1220   LInstruction* result =
1221       DefineAsRegister(new (zone()) LFlooringDivI(dividend, divisor));
1222   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1223       instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1224       (instr->CheckFlag(HValue::kCanOverflow) &&
1225        !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1226     result = AssignEnvironment(result);
1227   }
1228   return result;
1229 }
1230 
DoMathFloorOfDiv(HMathFloorOfDiv * instr)1231 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1232   if (instr->RightIsPowerOf2()) {
1233     return DoFlooringDivByPowerOf2I(instr);
1234   } else if (instr->right()->IsConstant()) {
1235     return DoFlooringDivByConstI(instr);
1236   } else {
1237     return DoFlooringDivI(instr);
1238   }
1239 }
1240 
DoModByPowerOf2I(HMod * instr)1241 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1242   DCHECK(instr->representation().IsSmiOrInteger32());
1243   DCHECK(instr->left()->representation().Equals(instr->representation()));
1244   DCHECK(instr->right()->representation().Equals(instr->representation()));
1245   LOperand* dividend = UseRegisterAtStart(instr->left());
1246   int32_t divisor = instr->right()->GetInteger32Constant();
1247   LInstruction* result =
1248       DefineSameAsFirst(new (zone()) LModByPowerOf2I(dividend, divisor));
1249   if (instr->CheckFlag(HValue::kLeftCanBeNegative) &&
1250       instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1251     result = AssignEnvironment(result);
1252   }
1253   return result;
1254 }
1255 
DoModByConstI(HMod * instr)1256 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1257   DCHECK(instr->representation().IsSmiOrInteger32());
1258   DCHECK(instr->left()->representation().Equals(instr->representation()));
1259   DCHECK(instr->right()->representation().Equals(instr->representation()));
1260   LOperand* dividend = UseRegister(instr->left());
1261   int32_t divisor = instr->right()->GetInteger32Constant();
1262   LInstruction* result =
1263       DefineAsRegister(new (zone()) LModByConstI(dividend, divisor));
1264   if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1265     result = AssignEnvironment(result);
1266   }
1267   return result;
1268 }
1269 
DoModI(HMod * instr)1270 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1271   DCHECK(instr->representation().IsSmiOrInteger32());
1272   DCHECK(instr->left()->representation().Equals(instr->representation()));
1273   DCHECK(instr->right()->representation().Equals(instr->representation()));
1274   LOperand* dividend = UseRegister(instr->left());
1275   LOperand* divisor = UseRegister(instr->right());
1276   LInstruction* result =
1277       DefineAsRegister(new (zone()) LModI(dividend, divisor));
1278   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1279       instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1280     result = AssignEnvironment(result);
1281   }
1282   return result;
1283 }
1284 
DoMod(HMod * instr)1285 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1286   if (instr->representation().IsSmiOrInteger32()) {
1287     if (instr->RightIsPowerOf2()) {
1288       return DoModByPowerOf2I(instr);
1289     } else if (instr->right()->IsConstant()) {
1290       return DoModByConstI(instr);
1291     } else {
1292       return DoModI(instr);
1293     }
1294   } else if (instr->representation().IsDouble()) {
1295     return DoArithmeticD(Token::MOD, instr);
1296   } else {
1297     return DoArithmeticT(Token::MOD, instr);
1298   }
1299 }
1300 
DoMul(HMul * instr)1301 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1302   if (instr->representation().IsSmiOrInteger32()) {
1303     DCHECK(instr->left()->representation().Equals(instr->representation()));
1304     DCHECK(instr->right()->representation().Equals(instr->representation()));
1305     HValue* left = instr->BetterLeftOperand();
1306     HValue* right = instr->BetterRightOperand();
1307     LOperand* left_op;
1308     LOperand* right_op;
1309     bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1310     bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
1311 
1312     int32_t constant_value = 0;
1313     if (right->IsConstant()) {
1314       HConstant* constant = HConstant::cast(right);
1315       constant_value = constant->Integer32Value();
1316       // Constants -1, 0 and 1 can be optimized if the result can overflow.
1317       // For other constants, it can be optimized only without overflow.
1318       if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) {
1319         left_op = UseRegisterAtStart(left);
1320         right_op = UseConstant(right);
1321       } else {
1322         if (bailout_on_minus_zero) {
1323           left_op = UseRegister(left);
1324         } else {
1325           left_op = UseRegisterAtStart(left);
1326         }
1327         right_op = UseRegister(right);
1328       }
1329     } else {
1330       if (bailout_on_minus_zero) {
1331         left_op = UseRegister(left);
1332       } else {
1333         left_op = UseRegisterAtStart(left);
1334       }
1335       right_op = UseRegister(right);
1336     }
1337     LMulI* mul = new (zone()) LMulI(left_op, right_op);
1338     if (right_op->IsConstantOperand()
1339             ? ((can_overflow && constant_value == -1) ||
1340                (bailout_on_minus_zero && constant_value <= 0))
1341             : (can_overflow || bailout_on_minus_zero)) {
1342       AssignEnvironment(mul);
1343     }
1344     return DefineAsRegister(mul);
1345 
1346   } else if (instr->representation().IsDouble()) {
1347     return DoArithmeticD(Token::MUL, instr);
1348   } else {
1349     return DoArithmeticT(Token::MUL, instr);
1350   }
1351 }
1352 
DoSub(HSub * instr)1353 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1354   if (instr->representation().IsSmiOrInteger32()) {
1355     DCHECK(instr->left()->representation().Equals(instr->representation()));
1356     DCHECK(instr->right()->representation().Equals(instr->representation()));
1357 
1358     LOperand* left = UseRegisterAtStart(instr->left());
1359     LOperand* right = UseOrConstantAtStart(instr->right());
1360     LSubI* sub = new (zone()) LSubI(left, right);
1361     LInstruction* result = DefineAsRegister(sub);
1362     if (instr->CheckFlag(HValue::kCanOverflow)) {
1363       result = AssignEnvironment(result);
1364     }
1365     return result;
1366   } else if (instr->representation().IsDouble()) {
1367     return DoArithmeticD(Token::SUB, instr);
1368   } else {
1369     return DoArithmeticT(Token::SUB, instr);
1370   }
1371 }
1372 
DoMultiplyAdd(HMul * mul,HValue * addend)1373 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) {
1374   LOperand* multiplier_op = UseRegister(mul->left());
1375   LOperand* multiplicand_op = UseRegister(mul->right());
1376   LOperand* addend_op = UseRegister(addend);
1377   return DefineAsRegister(
1378       new (zone()) LMultiplyAddD(addend_op, multiplier_op, multiplicand_op));
1379 }
1380 
DoMultiplySub(HValue * minuend,HMul * mul)1381 LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) {
1382   LOperand* minuend_op = UseRegister(minuend);
1383   LOperand* multiplier_op = UseRegister(mul->left());
1384   LOperand* multiplicand_op = UseRegister(mul->right());
1385 
1386   return DefineAsRegister(
1387       new (zone()) LMultiplySubD(minuend_op, multiplier_op, multiplicand_op));
1388 }
1389 
DoAdd(HAdd * instr)1390 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1391   if (instr->representation().IsSmiOrInteger32()) {
1392     DCHECK(instr->left()->representation().Equals(instr->representation()));
1393     DCHECK(instr->right()->representation().Equals(instr->representation()));
1394     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1395     LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1396     LAddI* add = new (zone()) LAddI(left, right);
1397     LInstruction* result = DefineAsRegister(add);
1398     if (instr->CheckFlag(HValue::kCanOverflow)) {
1399       result = AssignEnvironment(result);
1400     }
1401     return result;
1402   } else if (instr->representation().IsExternal()) {
1403     DCHECK(instr->IsConsistentExternalRepresentation());
1404     DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
1405     LOperand* left = UseRegisterAtStart(instr->left());
1406     LOperand* right = UseOrConstantAtStart(instr->right());
1407     LAddI* add = new (zone()) LAddI(left, right);
1408     LInstruction* result = DefineAsRegister(add);
1409     return result;
1410   } else if (instr->representation().IsDouble()) {
1411     return DoArithmeticD(Token::ADD, instr);
1412   } else {
1413     return DoArithmeticT(Token::ADD, instr);
1414   }
1415 }
1416 
DoMathMinMax(HMathMinMax * instr)1417 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1418   LOperand* left = NULL;
1419   LOperand* right = NULL;
1420   if (instr->representation().IsSmiOrInteger32()) {
1421     DCHECK(instr->left()->representation().Equals(instr->representation()));
1422     DCHECK(instr->right()->representation().Equals(instr->representation()));
1423     left = UseRegisterAtStart(instr->BetterLeftOperand());
1424     right = UseOrConstantAtStart(instr->BetterRightOperand());
1425   } else {
1426     DCHECK(instr->representation().IsDouble());
1427     DCHECK(instr->left()->representation().IsDouble());
1428     DCHECK(instr->right()->representation().IsDouble());
1429     left = UseRegister(instr->left());
1430     right = UseRegister(instr->right());
1431   }
1432   return DefineAsRegister(new (zone()) LMathMinMax(left, right));
1433 }
1434 
DoPower(HPower * instr)1435 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1436   DCHECK(instr->representation().IsDouble());
1437   // We call a C function for double power. It can't trigger a GC.
1438   // We need to use fixed result register for the call.
1439   Representation exponent_type = instr->right()->representation();
1440   DCHECK(instr->left()->representation().IsDouble());
1441   LOperand* left = UseFixedDouble(instr->left(), d1);
1442   LOperand* right = exponent_type.IsDouble()
1443                         ? UseFixedDouble(instr->right(), d2)
1444                         : UseFixed(instr->right(), r4);
1445   LPower* result = new (zone()) LPower(left, right);
1446   return MarkAsCall(DefineFixedDouble(result, d3), instr,
1447                     CAN_DEOPTIMIZE_EAGERLY);
1448 }
1449 
DoCompareGeneric(HCompareGeneric * instr)1450 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1451   DCHECK(instr->left()->representation().IsTagged());
1452   DCHECK(instr->right()->representation().IsTagged());
1453   LOperand* context = UseFixed(instr->context(), cp);
1454   LOperand* left = UseFixed(instr->left(), r3);
1455   LOperand* right = UseFixed(instr->right(), r2);
1456   LCmpT* result = new (zone()) LCmpT(context, left, right);
1457   return MarkAsCall(DefineFixed(result, r2), instr);
1458 }
1459 
DoCompareNumericAndBranch(HCompareNumericAndBranch * instr)1460 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1461     HCompareNumericAndBranch* instr) {
1462   Representation r = instr->representation();
1463   if (r.IsSmiOrInteger32()) {
1464     DCHECK(instr->left()->representation().Equals(r));
1465     DCHECK(instr->right()->representation().Equals(r));
1466     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1467     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1468     return new (zone()) LCompareNumericAndBranch(left, right);
1469   } else {
1470     DCHECK(r.IsDouble());
1471     DCHECK(instr->left()->representation().IsDouble());
1472     DCHECK(instr->right()->representation().IsDouble());
1473     LOperand* left = UseRegisterAtStart(instr->left());
1474     LOperand* right = UseRegisterAtStart(instr->right());
1475     return new (zone()) LCompareNumericAndBranch(left, right);
1476   }
1477 }
1478 
DoCompareObjectEqAndBranch(HCompareObjectEqAndBranch * instr)1479 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1480     HCompareObjectEqAndBranch* instr) {
1481   LOperand* left = UseRegisterAtStart(instr->left());
1482   LOperand* right = UseRegisterAtStart(instr->right());
1483   return new (zone()) LCmpObjectEqAndBranch(left, right);
1484 }
1485 
DoCompareHoleAndBranch(HCompareHoleAndBranch * instr)1486 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1487     HCompareHoleAndBranch* instr) {
1488   LOperand* value = UseRegisterAtStart(instr->value());
1489   return new (zone()) LCmpHoleAndBranch(value);
1490 }
1491 
DoIsStringAndBranch(HIsStringAndBranch * instr)1492 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1493   DCHECK(instr->value()->representation().IsTagged());
1494   LOperand* value = UseRegisterAtStart(instr->value());
1495   LOperand* temp = TempRegister();
1496   return new (zone()) LIsStringAndBranch(value, temp);
1497 }
1498 
DoIsSmiAndBranch(HIsSmiAndBranch * instr)1499 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1500   DCHECK(instr->value()->representation().IsTagged());
1501   return new (zone()) LIsSmiAndBranch(Use(instr->value()));
1502 }
1503 
DoIsUndetectableAndBranch(HIsUndetectableAndBranch * instr)1504 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1505     HIsUndetectableAndBranch* instr) {
1506   DCHECK(instr->value()->representation().IsTagged());
1507   LOperand* value = UseRegisterAtStart(instr->value());
1508   return new (zone()) LIsUndetectableAndBranch(value, TempRegister());
1509 }
1510 
DoStringCompareAndBranch(HStringCompareAndBranch * instr)1511 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1512     HStringCompareAndBranch* instr) {
1513   DCHECK(instr->left()->representation().IsTagged());
1514   DCHECK(instr->right()->representation().IsTagged());
1515   LOperand* context = UseFixed(instr->context(), cp);
1516   LOperand* left = UseFixed(instr->left(), r3);
1517   LOperand* right = UseFixed(instr->right(), r2);
1518   LStringCompareAndBranch* result =
1519       new (zone()) LStringCompareAndBranch(context, left, right);
1520   return MarkAsCall(result, instr);
1521 }
1522 
DoHasInstanceTypeAndBranch(HHasInstanceTypeAndBranch * instr)1523 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1524     HHasInstanceTypeAndBranch* instr) {
1525   DCHECK(instr->value()->representation().IsTagged());
1526   LOperand* value = UseRegisterAtStart(instr->value());
1527   return new (zone()) LHasInstanceTypeAndBranch(value);
1528 }
1529 
DoClassOfTestAndBranch(HClassOfTestAndBranch * instr)1530 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1531     HClassOfTestAndBranch* instr) {
1532   DCHECK(instr->value()->representation().IsTagged());
1533   LOperand* value = UseRegister(instr->value());
1534   return new (zone()) LClassOfTestAndBranch(value, TempRegister());
1535 }
1536 
DoSeqStringGetChar(HSeqStringGetChar * instr)1537 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1538   LOperand* string = UseRegisterAtStart(instr->string());
1539   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1540   return DefineAsRegister(new (zone()) LSeqStringGetChar(string, index));
1541 }
1542 
DoSeqStringSetChar(HSeqStringSetChar * instr)1543 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1544   LOperand* string = UseRegisterAtStart(instr->string());
1545   LOperand* index = FLAG_debug_code
1546                         ? UseRegisterAtStart(instr->index())
1547                         : UseRegisterOrConstantAtStart(instr->index());
1548   LOperand* value = UseRegisterAtStart(instr->value());
1549   LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL;
1550   return new (zone()) LSeqStringSetChar(context, string, index, value);
1551 }
1552 
DoBoundsCheck(HBoundsCheck * instr)1553 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1554   if (!FLAG_debug_code && instr->skip_check()) return NULL;
1555   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1556   LOperand* length = !index->IsConstantOperand()
1557                          ? UseRegisterOrConstantAtStart(instr->length())
1558                          : UseRegisterAtStart(instr->length());
1559   LInstruction* result = new (zone()) LBoundsCheck(index, length);
1560   if (!FLAG_debug_code || !instr->skip_check()) {
1561     result = AssignEnvironment(result);
1562   }
1563   return result;
1564 }
1565 
DoAbnormalExit(HAbnormalExit * instr)1566 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1567   // The control instruction marking the end of a block that completed
1568   // abruptly (e.g., threw an exception).  There is nothing specific to do.
1569   return NULL;
1570 }
1571 
DoUseConst(HUseConst * instr)1572 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { return NULL; }
1573 
DoForceRepresentation(HForceRepresentation * bad)1574 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1575   // All HForceRepresentation instructions should be eliminated in the
1576   // representation change phase of Hydrogen.
1577   UNREACHABLE();
1578   return NULL;
1579 }
1580 
DoChange(HChange * instr)1581 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1582   Representation from = instr->from();
1583   Representation to = instr->to();
1584   HValue* val = instr->value();
1585   if (from.IsSmi()) {
1586     if (to.IsTagged()) {
1587       LOperand* value = UseRegister(val);
1588       return DefineSameAsFirst(new (zone()) LDummyUse(value));
1589     }
1590     from = Representation::Tagged();
1591   }
1592   if (from.IsTagged()) {
1593     if (to.IsDouble()) {
1594       LOperand* value = UseRegister(val);
1595       LInstruction* result =
1596           DefineAsRegister(new (zone()) LNumberUntagD(value));
1597       if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1598       return result;
1599     } else if (to.IsSmi()) {
1600       LOperand* value = UseRegister(val);
1601       if (val->type().IsSmi()) {
1602         return DefineSameAsFirst(new (zone()) LDummyUse(value));
1603       }
1604       return AssignEnvironment(
1605           DefineSameAsFirst(new (zone()) LCheckSmi(value)));
1606     } else {
1607       DCHECK(to.IsInteger32());
1608       if (val->type().IsSmi() || val->representation().IsSmi()) {
1609         LOperand* value = UseRegisterAtStart(val);
1610         return DefineAsRegister(new (zone()) LSmiUntag(value, false));
1611       } else {
1612         LOperand* value = UseRegister(val);
1613         LOperand* temp1 = TempRegister();
1614         LOperand* temp2 = TempDoubleRegister();
1615         LInstruction* result =
1616             DefineSameAsFirst(new (zone()) LTaggedToI(value, temp1, temp2));
1617         if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1618         return result;
1619       }
1620     }
1621   } else if (from.IsDouble()) {
1622     if (to.IsTagged()) {
1623       info()->MarkAsDeferredCalling();
1624       LOperand* value = UseRegister(val);
1625       LOperand* temp1 = TempRegister();
1626       LOperand* temp2 = TempRegister();
1627       LUnallocated* result_temp = TempRegister();
1628       LNumberTagD* result = new (zone()) LNumberTagD(value, temp1, temp2);
1629       return AssignPointerMap(Define(result, result_temp));
1630     } else if (to.IsSmi()) {
1631       LOperand* value = UseRegister(val);
1632       return AssignEnvironment(
1633           DefineAsRegister(new (zone()) LDoubleToSmi(value)));
1634     } else {
1635       DCHECK(to.IsInteger32());
1636       LOperand* value = UseRegister(val);
1637       LInstruction* result = DefineAsRegister(new (zone()) LDoubleToI(value));
1638       if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result);
1639       return result;
1640     }
1641   } else if (from.IsInteger32()) {
1642     info()->MarkAsDeferredCalling();
1643     if (to.IsTagged()) {
1644       if (!instr->CheckFlag(HValue::kCanOverflow)) {
1645         LOperand* value = UseRegisterAtStart(val);
1646         return DefineAsRegister(new (zone()) LSmiTag(value));
1647       } else if (val->CheckFlag(HInstruction::kUint32)) {
1648         LOperand* value = UseRegisterAtStart(val);
1649         LOperand* temp1 = TempRegister();
1650         LOperand* temp2 = TempRegister();
1651         LNumberTagU* result = new (zone()) LNumberTagU(value, temp1, temp2);
1652         return AssignPointerMap(DefineAsRegister(result));
1653       } else {
1654         LOperand* value = UseRegisterAtStart(val);
1655         LOperand* temp1 = TempRegister();
1656         LOperand* temp2 = TempRegister();
1657         LNumberTagI* result = new (zone()) LNumberTagI(value, temp1, temp2);
1658         return AssignPointerMap(DefineAsRegister(result));
1659       }
1660     } else if (to.IsSmi()) {
1661       LOperand* value = UseRegister(val);
1662       LInstruction* result = DefineAsRegister(new (zone()) LSmiTag(value));
1663       if (instr->CheckFlag(HValue::kCanOverflow)) {
1664         result = AssignEnvironment(result);
1665       }
1666       return result;
1667     } else {
1668       DCHECK(to.IsDouble());
1669       if (val->CheckFlag(HInstruction::kUint32)) {
1670         return DefineAsRegister(new (zone()) LUint32ToDouble(UseRegister(val)));
1671       } else {
1672         return DefineAsRegister(new (zone()) LInteger32ToDouble(Use(val)));
1673       }
1674     }
1675   }
1676   UNREACHABLE();
1677   return NULL;
1678 }
1679 
DoCheckHeapObject(HCheckHeapObject * instr)1680 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
1681   LOperand* value = UseAtStart(instr->value());
1682   LInstruction* result = new (zone()) LCheckNonSmi(value);
1683   if (!instr->value()->type().IsHeapObject()) {
1684     result = AssignEnvironment(result);
1685   }
1686   return result;
1687 }
1688 
DoCheckSmi(HCheckSmi * instr)1689 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1690   LOperand* value = UseAtStart(instr->value());
1691   return AssignEnvironment(new (zone()) LCheckSmi(value));
1692 }
1693 
DoCheckArrayBufferNotNeutered(HCheckArrayBufferNotNeutered * instr)1694 LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
1695     HCheckArrayBufferNotNeutered* instr) {
1696   LOperand* view = UseRegisterAtStart(instr->value());
1697   LCheckArrayBufferNotNeutered* result =
1698       new (zone()) LCheckArrayBufferNotNeutered(view);
1699   return AssignEnvironment(result);
1700 }
1701 
DoCheckInstanceType(HCheckInstanceType * instr)1702 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1703   LOperand* value = UseRegisterAtStart(instr->value());
1704   LInstruction* result = new (zone()) LCheckInstanceType(value);
1705   return AssignEnvironment(result);
1706 }
1707 
DoCheckValue(HCheckValue * instr)1708 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
1709   LOperand* value = UseRegisterAtStart(instr->value());
1710   return AssignEnvironment(new (zone()) LCheckValue(value));
1711 }
1712 
DoCheckMaps(HCheckMaps * instr)1713 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1714   if (instr->IsStabilityCheck()) return new (zone()) LCheckMaps;
1715   LOperand* value = UseRegisterAtStart(instr->value());
1716   LOperand* temp = TempRegister();
1717   LInstruction* result =
1718       AssignEnvironment(new (zone()) LCheckMaps(value, temp));
1719   if (instr->HasMigrationTarget()) {
1720     info()->MarkAsDeferredCalling();
1721     result = AssignPointerMap(result);
1722   }
1723   return result;
1724 }
1725 
DoClampToUint8(HClampToUint8 * instr)1726 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1727   HValue* value = instr->value();
1728   Representation input_rep = value->representation();
1729   LOperand* reg = UseRegister(value);
1730   if (input_rep.IsDouble()) {
1731     return DefineAsRegister(new (zone()) LClampDToUint8(reg));
1732   } else if (input_rep.IsInteger32()) {
1733     return DefineAsRegister(new (zone()) LClampIToUint8(reg));
1734   } else {
1735     DCHECK(input_rep.IsSmiOrTagged());
1736     LClampTToUint8* result =
1737         new (zone()) LClampTToUint8(reg, TempDoubleRegister());
1738     return AssignEnvironment(DefineAsRegister(result));
1739   }
1740 }
1741 
DoReturn(HReturn * instr)1742 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1743   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), cp) : NULL;
1744   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1745   return new (zone())
1746       LReturn(UseFixed(instr->value(), r2), context, parameter_count);
1747 }
1748 
DoConstant(HConstant * instr)1749 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1750   Representation r = instr->representation();
1751   if (r.IsSmi()) {
1752     return DefineAsRegister(new (zone()) LConstantS);
1753   } else if (r.IsInteger32()) {
1754     return DefineAsRegister(new (zone()) LConstantI);
1755   } else if (r.IsDouble()) {
1756     return DefineAsRegister(new (zone()) LConstantD);
1757   } else if (r.IsExternal()) {
1758     return DefineAsRegister(new (zone()) LConstantE);
1759   } else if (r.IsTagged()) {
1760     return DefineAsRegister(new (zone()) LConstantT);
1761   } else {
1762     UNREACHABLE();
1763     return NULL;
1764   }
1765 }
1766 
DoLoadContextSlot(HLoadContextSlot * instr)1767 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1768   LOperand* context = UseRegisterAtStart(instr->value());
1769   LInstruction* result =
1770       DefineAsRegister(new (zone()) LLoadContextSlot(context));
1771   if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
1772     result = AssignEnvironment(result);
1773   }
1774   return result;
1775 }
1776 
DoStoreContextSlot(HStoreContextSlot * instr)1777 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1778   LOperand* context;
1779   LOperand* value;
1780   if (instr->NeedsWriteBarrier()) {
1781     context = UseTempRegister(instr->context());
1782     value = UseTempRegister(instr->value());
1783   } else {
1784     context = UseRegister(instr->context());
1785     value = UseRegister(instr->value());
1786   }
1787   LInstruction* result = new (zone()) LStoreContextSlot(context, value);
1788   if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
1789     result = AssignEnvironment(result);
1790   }
1791   return result;
1792 }
1793 
DoLoadNamedField(HLoadNamedField * instr)1794 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1795   LOperand* obj = UseRegisterAtStart(instr->object());
1796   return DefineAsRegister(new (zone()) LLoadNamedField(obj));
1797 }
1798 
DoLoadFunctionPrototype(HLoadFunctionPrototype * instr)1799 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1800     HLoadFunctionPrototype* instr) {
1801   return AssignEnvironment(DefineAsRegister(
1802       new (zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
1803 }
1804 
DoLoadRoot(HLoadRoot * instr)1805 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
1806   return DefineAsRegister(new (zone()) LLoadRoot);
1807 }
1808 
DoLoadKeyed(HLoadKeyed * instr)1809 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
1810   DCHECK(instr->key()->representation().IsSmiOrInteger32());
1811   ElementsKind elements_kind = instr->elements_kind();
1812   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1813   LInstruction* result = NULL;
1814 
1815   if (!instr->is_fixed_typed_array()) {
1816     LOperand* obj = NULL;
1817     if (instr->representation().IsDouble()) {
1818       obj = UseRegister(instr->elements());
1819     } else {
1820       obj = UseRegisterAtStart(instr->elements());
1821     }
1822     result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
1823   } else {
1824     DCHECK((instr->representation().IsInteger32() &&
1825             !IsDoubleOrFloatElementsKind(elements_kind)) ||
1826            (instr->representation().IsDouble() &&
1827             IsDoubleOrFloatElementsKind(elements_kind)));
1828     LOperand* backing_store = UseRegister(instr->elements());
1829     LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
1830     result = DefineAsRegister(
1831         new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
1832   }
1833 
1834   bool needs_environment;
1835   if (instr->is_fixed_typed_array()) {
1836     // see LCodeGen::DoLoadKeyedExternalArray
1837     needs_environment = elements_kind == UINT32_ELEMENTS &&
1838                         !instr->CheckFlag(HInstruction::kUint32);
1839   } else {
1840     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
1841     // LCodeGen::DoLoadKeyedFixedArray
1842     needs_environment =
1843         instr->RequiresHoleCheck() ||
1844         (instr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED && info()->IsStub());
1845   }
1846 
1847   if (needs_environment) {
1848     result = AssignEnvironment(result);
1849   }
1850   return result;
1851 }
1852 
DoStoreKeyed(HStoreKeyed * instr)1853 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
1854   if (!instr->is_fixed_typed_array()) {
1855     DCHECK(instr->elements()->representation().IsTagged());
1856     bool needs_write_barrier = instr->NeedsWriteBarrier();
1857     LOperand* object = NULL;
1858     LOperand* key = NULL;
1859     LOperand* val = NULL;
1860 
1861     if (instr->value()->representation().IsDouble()) {
1862       object = UseRegisterAtStart(instr->elements());
1863       val = UseRegister(instr->value());
1864       key = UseRegisterOrConstantAtStart(instr->key());
1865     } else {
1866       if (needs_write_barrier) {
1867         object = UseTempRegister(instr->elements());
1868         val = UseTempRegister(instr->value());
1869         key = UseTempRegister(instr->key());
1870       } else {
1871         object = UseRegisterAtStart(instr->elements());
1872         val = UseRegisterAtStart(instr->value());
1873         key = UseRegisterOrConstantAtStart(instr->key());
1874       }
1875     }
1876 
1877     return new (zone()) LStoreKeyed(object, key, val, nullptr);
1878   }
1879 
1880   DCHECK((instr->value()->representation().IsInteger32() &&
1881           !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
1882          (instr->value()->representation().IsDouble() &&
1883           IsDoubleOrFloatElementsKind(instr->elements_kind())));
1884   DCHECK(instr->elements()->representation().IsExternal());
1885   LOperand* val = UseRegister(instr->value());
1886   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1887   LOperand* backing_store = UseRegister(instr->elements());
1888   LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
1889   return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
1890 }
1891 
DoTransitionElementsKind(HTransitionElementsKind * instr)1892 LInstruction* LChunkBuilder::DoTransitionElementsKind(
1893     HTransitionElementsKind* instr) {
1894   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
1895     LOperand* object = UseRegister(instr->object());
1896     LOperand* new_map_reg = TempRegister();
1897     LTransitionElementsKind* result =
1898         new (zone()) LTransitionElementsKind(object, NULL, new_map_reg);
1899     return result;
1900   } else {
1901     LOperand* object = UseFixed(instr->object(), r2);
1902     LOperand* context = UseFixed(instr->context(), cp);
1903     LTransitionElementsKind* result =
1904         new (zone()) LTransitionElementsKind(object, context, NULL);
1905     return MarkAsCall(result, instr);
1906   }
1907 }
1908 
DoTrapAllocationMemento(HTrapAllocationMemento * instr)1909 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
1910     HTrapAllocationMemento* instr) {
1911   LOperand* object = UseRegister(instr->object());
1912   LOperand* temp1 = TempRegister();
1913   LOperand* temp2 = TempRegister();
1914   LTrapAllocationMemento* result =
1915       new (zone()) LTrapAllocationMemento(object, temp1, temp2);
1916   return AssignEnvironment(result);
1917 }
1918 
DoMaybeGrowElements(HMaybeGrowElements * instr)1919 LInstruction* LChunkBuilder::DoMaybeGrowElements(HMaybeGrowElements* instr) {
1920   info()->MarkAsDeferredCalling();
1921   LOperand* context = UseFixed(instr->context(), cp);
1922   LOperand* object = Use(instr->object());
1923   LOperand* elements = Use(instr->elements());
1924   LOperand* key = UseRegisterOrConstant(instr->key());
1925   LOperand* current_capacity = UseRegisterOrConstant(instr->current_capacity());
1926 
1927   LMaybeGrowElements* result = new (zone())
1928       LMaybeGrowElements(context, object, elements, key, current_capacity);
1929   DefineFixed(result, r2);
1930   return AssignPointerMap(AssignEnvironment(result));
1931 }
1932 
DoStoreNamedField(HStoreNamedField * instr)1933 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
1934   bool is_in_object = instr->access().IsInobject();
1935   bool needs_write_barrier = instr->NeedsWriteBarrier();
1936   bool needs_write_barrier_for_map =
1937       instr->has_transition() && instr->NeedsWriteBarrierForMap();
1938 
1939   LOperand* obj;
1940   if (needs_write_barrier) {
1941     obj = is_in_object ? UseRegister(instr->object())
1942                        : UseTempRegister(instr->object());
1943   } else {
1944     obj = needs_write_barrier_for_map ? UseRegister(instr->object())
1945                                       : UseRegisterAtStart(instr->object());
1946   }
1947 
1948   LOperand* val;
1949   if (needs_write_barrier) {
1950     val = UseTempRegister(instr->value());
1951   } else if (instr->field_representation().IsDouble()) {
1952     val = UseRegisterAtStart(instr->value());
1953   } else {
1954     val = UseRegister(instr->value());
1955   }
1956 
1957   // We need a temporary register for write barrier of the map field.
1958   LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
1959 
1960   return new (zone()) LStoreNamedField(obj, val, temp);
1961 }
1962 
DoStringAdd(HStringAdd * instr)1963 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
1964   LOperand* context = UseFixed(instr->context(), cp);
1965   LOperand* left = UseFixed(instr->left(), r3);
1966   LOperand* right = UseFixed(instr->right(), r2);
1967   return MarkAsCall(
1968       DefineFixed(new (zone()) LStringAdd(context, left, right), r2), instr);
1969 }
1970 
DoStringCharCodeAt(HStringCharCodeAt * instr)1971 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
1972   LOperand* string = UseTempRegister(instr->string());
1973   LOperand* index = UseTempRegister(instr->index());
1974   LOperand* context = UseAny(instr->context());
1975   LStringCharCodeAt* result =
1976       new (zone()) LStringCharCodeAt(context, string, index);
1977   return AssignPointerMap(DefineAsRegister(result));
1978 }
1979 
DoStringCharFromCode(HStringCharFromCode * instr)1980 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
1981   LOperand* char_code = UseRegister(instr->value());
1982   LOperand* context = UseAny(instr->context());
1983   LStringCharFromCode* result =
1984       new (zone()) LStringCharFromCode(context, char_code);
1985   return AssignPointerMap(DefineAsRegister(result));
1986 }
1987 
DoAllocate(HAllocate * instr)1988 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
1989   LOperand* size = UseRegisterOrConstant(instr->size());
1990   LOperand* temp1 = TempRegister();
1991   LOperand* temp2 = TempRegister();
1992   if (instr->IsAllocationFolded()) {
1993     LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
1994     return DefineAsRegister(result);
1995   } else {
1996     info()->MarkAsDeferredCalling();
1997     LOperand* context = UseAny(instr->context());
1998     LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
1999     return AssignPointerMap(DefineAsRegister(result));
2000   }
2001 }
2002 
DoOsrEntry(HOsrEntry * instr)2003 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2004   DCHECK(argument_count_ == 0);
2005   allocator_->MarkAsOsrEntry();
2006   current_block_->last_environment()->set_ast_id(instr->ast_id());
2007   return AssignEnvironment(new (zone()) LOsrEntry);
2008 }
2009 
DoParameter(HParameter * instr)2010 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2011   LParameter* result = new (zone()) LParameter;
2012   if (instr->kind() == HParameter::STACK_PARAMETER) {
2013     int spill_index = chunk()->GetParameterStackSlot(instr->index());
2014     return DefineAsSpilled(result, spill_index);
2015   } else {
2016     DCHECK(info()->IsStub());
2017     CallInterfaceDescriptor descriptor = graph()->descriptor();
2018     int index = static_cast<int>(instr->index());
2019     Register reg = descriptor.GetRegisterParameter(index);
2020     return DefineFixed(result, reg);
2021   }
2022 }
2023 
DoUnknownOSRValue(HUnknownOSRValue * instr)2024 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2025   // Use an index that corresponds to the location in the unoptimized frame,
2026   // which the optimized frame will subsume.
2027   int env_index = instr->index();
2028   int spill_index = 0;
2029   if (instr->environment()->is_parameter_index(env_index)) {
2030     spill_index = chunk()->GetParameterStackSlot(env_index);
2031   } else {
2032     spill_index = env_index - instr->environment()->first_local_index();
2033     if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
2034       Retry(kTooManySpillSlotsNeededForOSR);
2035       spill_index = 0;
2036     }
2037     spill_index += StandardFrameConstants::kFixedSlotCount;
2038   }
2039   return DefineAsSpilled(new (zone()) LUnknownOSRValue, spill_index);
2040 }
2041 
DoArgumentsObject(HArgumentsObject * instr)2042 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2043   // There are no real uses of the arguments object.
2044   // arguments.length and element access are supported directly on
2045   // stack arguments, and any real arguments object use causes a bailout.
2046   // So this value is never used.
2047   return NULL;
2048 }
2049 
DoCapturedObject(HCapturedObject * instr)2050 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2051   instr->ReplayEnvironment(current_block_->last_environment());
2052 
2053   // There are no real uses of a captured object.
2054   return NULL;
2055 }
2056 
DoAccessArgumentsAt(HAccessArgumentsAt * instr)2057 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2058   info()->MarkAsRequiresFrame();
2059   LOperand* args = UseRegister(instr->arguments());
2060   LOperand* length = UseRegisterOrConstantAtStart(instr->length());
2061   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
2062   return DefineAsRegister(new (zone()) LAccessArgumentsAt(args, length, index));
2063 }
2064 
DoTypeof(HTypeof * instr)2065 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2066   LOperand* context = UseFixed(instr->context(), cp);
2067   LOperand* value = UseFixed(instr->value(), r5);
2068   LTypeof* result = new (zone()) LTypeof(context, value);
2069   return MarkAsCall(DefineFixed(result, r2), instr);
2070 }
2071 
DoTypeofIsAndBranch(HTypeofIsAndBranch * instr)2072 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2073   return new (zone()) LTypeofIsAndBranch(UseRegister(instr->value()));
2074 }
2075 
DoSimulate(HSimulate * instr)2076 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2077   instr->ReplayEnvironment(current_block_->last_environment());
2078   return NULL;
2079 }
2080 
DoStackCheck(HStackCheck * instr)2081 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2082   if (instr->is_function_entry()) {
2083     LOperand* context = UseFixed(instr->context(), cp);
2084     return MarkAsCall(new (zone()) LStackCheck(context), instr);
2085   } else {
2086     DCHECK(instr->is_backwards_branch());
2087     LOperand* context = UseAny(instr->context());
2088     return AssignEnvironment(
2089         AssignPointerMap(new (zone()) LStackCheck(context)));
2090   }
2091 }
2092 
DoEnterInlined(HEnterInlined * instr)2093 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2094   HEnvironment* outer = current_block_->last_environment();
2095   outer->set_ast_id(instr->ReturnId());
2096   HConstant* undefined = graph()->GetConstantUndefined();
2097   HEnvironment* inner = outer->CopyForInlining(
2098       instr->closure(), instr->arguments_count(), instr->function(), undefined,
2099       instr->inlining_kind(), instr->syntactic_tail_call_mode());
2100   // Only replay binding of arguments object if it wasn't removed from graph.
2101   if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
2102     inner->Bind(instr->arguments_var(), instr->arguments_object());
2103   }
2104   inner->BindContext(instr->closure_context());
2105   inner->set_entry(instr);
2106   current_block_->UpdateEnvironment(inner);
2107   return NULL;
2108 }
2109 
DoLeaveInlined(HLeaveInlined * instr)2110 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2111   LInstruction* pop = NULL;
2112 
2113   HEnvironment* env = current_block_->last_environment();
2114 
2115   if (env->entry()->arguments_pushed()) {
2116     int argument_count = env->arguments_environment()->parameter_count();
2117     pop = new (zone()) LDrop(argument_count);
2118     DCHECK(instr->argument_delta() == -argument_count);
2119   }
2120 
2121   HEnvironment* outer =
2122       current_block_->last_environment()->DiscardInlined(false);
2123   current_block_->UpdateEnvironment(outer);
2124 
2125   return pop;
2126 }
2127 
DoForInPrepareMap(HForInPrepareMap * instr)2128 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2129   LOperand* context = UseFixed(instr->context(), cp);
2130   LOperand* object = UseFixed(instr->enumerable(), r2);
2131   LForInPrepareMap* result = new (zone()) LForInPrepareMap(context, object);
2132   return MarkAsCall(DefineFixed(result, r2), instr, CAN_DEOPTIMIZE_EAGERLY);
2133 }
2134 
DoForInCacheArray(HForInCacheArray * instr)2135 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2136   LOperand* map = UseRegister(instr->map());
2137   return AssignEnvironment(
2138       DefineAsRegister(new (zone()) LForInCacheArray(map)));
2139 }
2140 
DoCheckMapValue(HCheckMapValue * instr)2141 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2142   LOperand* value = UseRegisterAtStart(instr->value());
2143   LOperand* map = UseRegisterAtStart(instr->map());
2144   return AssignEnvironment(new (zone()) LCheckMapValue(value, map));
2145 }
2146 
DoLoadFieldByIndex(HLoadFieldByIndex * instr)2147 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2148   LOperand* object = UseRegister(instr->object());
2149   LOperand* index = UseTempRegister(instr->index());
2150   LLoadFieldByIndex* load = new (zone()) LLoadFieldByIndex(object, index);
2151   LInstruction* result = DefineSameAsFirst(load);
2152   return AssignPointerMap(result);
2153 }
2154 
2155 }  // namespace internal
2156 }  // namespace v8
2157