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