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