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