• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #if defined(V8_TARGET_ARCH_IA32)
31 
32 #include "lithium-allocator-inl.h"
33 #include "ia32/lithium-ia32.h"
34 #include "ia32/lithium-codegen-ia32.h"
35 
36 namespace v8 {
37 namespace internal {
38 
39 #define DEFINE_COMPILE(type)                            \
40   void L##type::CompileToNative(LCodeGen* generator) {  \
41     generator->Do##type(this);                          \
42   }
LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)43 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
44 #undef DEFINE_COMPILE
45 
46 LOsrEntry::LOsrEntry() {
47   for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
48     register_spills_[i] = NULL;
49   }
50   for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
51     double_register_spills_[i] = NULL;
52   }
53 }
54 
55 
MarkSpilledRegister(int allocation_index,LOperand * spill_operand)56 void LOsrEntry::MarkSpilledRegister(int allocation_index,
57                                     LOperand* spill_operand) {
58   ASSERT(spill_operand->IsStackSlot());
59   ASSERT(register_spills_[allocation_index] == NULL);
60   register_spills_[allocation_index] = spill_operand;
61 }
62 
63 
MarkSpilledDoubleRegister(int allocation_index,LOperand * spill_operand)64 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
65                                           LOperand* spill_operand) {
66   ASSERT(spill_operand->IsDoubleStackSlot());
67   ASSERT(double_register_spills_[allocation_index] == NULL);
68   double_register_spills_[allocation_index] = spill_operand;
69 }
70 
71 
72 #ifdef DEBUG
VerifyCall()73 void LInstruction::VerifyCall() {
74   // Call instructions can use only fixed registers as temporaries and
75   // outputs because all registers are blocked by the calling convention.
76   // Inputs operands must use a fixed register or use-at-start policy or
77   // a non-register policy.
78   ASSERT(Output() == NULL ||
79          LUnallocated::cast(Output())->HasFixedPolicy() ||
80          !LUnallocated::cast(Output())->HasRegisterPolicy());
81   for (UseIterator it(this); !it.Done(); it.Advance()) {
82     LUnallocated* operand = LUnallocated::cast(it.Current());
83     ASSERT(operand->HasFixedPolicy() ||
84            operand->IsUsedAtStart());
85   }
86   for (TempIterator it(this); !it.Done(); it.Advance()) {
87     LUnallocated* operand = LUnallocated::cast(it.Current());
88     ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
89   }
90 }
91 #endif
92 
93 
PrintTo(StringStream * stream)94 void LInstruction::PrintTo(StringStream* stream) {
95   stream->Add("%s ", this->Mnemonic());
96 
97   PrintOutputOperandTo(stream);
98 
99   PrintDataTo(stream);
100 
101   if (HasEnvironment()) {
102     stream->Add(" ");
103     environment()->PrintTo(stream);
104   }
105 
106   if (HasPointerMap()) {
107     stream->Add(" ");
108     pointer_map()->PrintTo(stream);
109   }
110 }
111 
112 
PrintDataTo(StringStream * stream)113 void LInstruction::PrintDataTo(StringStream* stream) {
114   stream->Add("= ");
115   for (int i = 0; i < InputCount(); i++) {
116     if (i > 0) stream->Add(" ");
117     InputAt(i)->PrintTo(stream);
118   }
119 }
120 
121 
PrintOutputOperandTo(StringStream * stream)122 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
123   if (HasResult()) result()->PrintTo(stream);
124 }
125 
126 
PrintDataTo(StringStream * stream)127 void LLabel::PrintDataTo(StringStream* stream) {
128   LGap::PrintDataTo(stream);
129   LLabel* rep = replacement();
130   if (rep != NULL) {
131     stream->Add(" Dead block replaced with B%d", rep->block_id());
132   }
133 }
134 
135 
IsRedundant() const136 bool LGap::IsRedundant() const {
137   for (int i = 0; i < 4; i++) {
138     if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
139       return false;
140     }
141   }
142 
143   return true;
144 }
145 
146 
PrintDataTo(StringStream * stream)147 void LGap::PrintDataTo(StringStream* stream) {
148   for (int i = 0; i < 4; i++) {
149     stream->Add("(");
150     if (parallel_moves_[i] != NULL) {
151       parallel_moves_[i]->PrintDataTo(stream);
152     }
153     stream->Add(") ");
154   }
155 }
156 
157 
Mnemonic() const158 const char* LArithmeticD::Mnemonic() const {
159   switch (op()) {
160     case Token::ADD: return "add-d";
161     case Token::SUB: return "sub-d";
162     case Token::MUL: return "mul-d";
163     case Token::DIV: return "div-d";
164     case Token::MOD: return "mod-d";
165     default:
166       UNREACHABLE();
167       return NULL;
168   }
169 }
170 
171 
Mnemonic() const172 const char* LArithmeticT::Mnemonic() const {
173   switch (op()) {
174     case Token::ADD: return "add-t";
175     case Token::SUB: return "sub-t";
176     case Token::MUL: return "mul-t";
177     case Token::MOD: return "mod-t";
178     case Token::DIV: return "div-t";
179     case Token::BIT_AND: return "bit-and-t";
180     case Token::BIT_OR: return "bit-or-t";
181     case Token::BIT_XOR: return "bit-xor-t";
182     case Token::SHL: return "sal-t";
183     case Token::SAR: return "sar-t";
184     case Token::SHR: return "shr-t";
185     default:
186       UNREACHABLE();
187       return NULL;
188   }
189 }
190 
191 
PrintDataTo(StringStream * stream)192 void LGoto::PrintDataTo(StringStream* stream) {
193   stream->Add("B%d", block_id());
194 }
195 
196 
PrintDataTo(StringStream * stream)197 void LBranch::PrintDataTo(StringStream* stream) {
198   stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
199   InputAt(0)->PrintTo(stream);
200 }
201 
202 
PrintDataTo(StringStream * stream)203 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
204   stream->Add("if ");
205   InputAt(0)->PrintTo(stream);
206   stream->Add(" %s ", Token::String(op()));
207   InputAt(1)->PrintTo(stream);
208   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
209 }
210 
211 
PrintDataTo(StringStream * stream)212 void LIsNilAndBranch::PrintDataTo(StringStream* stream) {
213   stream->Add("if ");
214   InputAt(0)->PrintTo(stream);
215   stream->Add(kind() == kStrictEquality ? " === " : " == ");
216   stream->Add(nil() == kNullValue ? "null" : "undefined");
217   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
218 }
219 
220 
PrintDataTo(StringStream * stream)221 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
222   stream->Add("if is_object(");
223   InputAt(0)->PrintTo(stream);
224   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
225 }
226 
227 
PrintDataTo(StringStream * stream)228 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
229   stream->Add("if is_string(");
230   InputAt(0)->PrintTo(stream);
231   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
232 }
233 
234 
PrintDataTo(StringStream * stream)235 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
236   stream->Add("if is_smi(");
237   InputAt(0)->PrintTo(stream);
238   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
239 }
240 
241 
PrintDataTo(StringStream * stream)242 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
243   stream->Add("if is_undetectable(");
244   InputAt(0)->PrintTo(stream);
245   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
246 }
247 
248 
PrintDataTo(StringStream * stream)249 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
250   stream->Add("if string_compare(");
251   InputAt(1)->PrintTo(stream);
252   InputAt(2)->PrintTo(stream);
253   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
254 }
255 
256 
PrintDataTo(StringStream * stream)257 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
258   stream->Add("if has_instance_type(");
259   InputAt(0)->PrintTo(stream);
260   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
261 }
262 
263 
PrintDataTo(StringStream * stream)264 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
265   stream->Add("if has_cached_array_index(");
266   InputAt(0)->PrintTo(stream);
267   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
268 }
269 
270 
PrintDataTo(StringStream * stream)271 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
272   stream->Add("if class_of_test(");
273   InputAt(0)->PrintTo(stream);
274   stream->Add(", \"%o\") then B%d else B%d",
275               *hydrogen()->class_name(),
276               true_block_id(),
277               false_block_id());
278 }
279 
280 
PrintDataTo(StringStream * stream)281 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
282   stream->Add("if typeof ");
283   InputAt(0)->PrintTo(stream);
284   stream->Add(" == \"%s\" then B%d else B%d",
285               *hydrogen()->type_literal()->ToCString(),
286               true_block_id(), false_block_id());
287 }
288 
289 
PrintDataTo(StringStream * stream)290 void LCallConstantFunction::PrintDataTo(StringStream* stream) {
291   stream->Add("#%d / ", arity());
292 }
293 
294 
PrintDataTo(StringStream * stream)295 void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
296   stream->Add("/%s ", hydrogen()->OpName());
297   InputAt(0)->PrintTo(stream);
298 }
299 
300 
PrintDataTo(StringStream * stream)301 void LMathPowHalf::PrintDataTo(StringStream* stream) {
302   stream->Add("/pow_half ");
303   InputAt(0)->PrintTo(stream);
304 }
305 
306 
PrintDataTo(StringStream * stream)307 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
308   InputAt(0)->PrintTo(stream);
309   stream->Add("[%d]", slot_index());
310 }
311 
312 
PrintDataTo(StringStream * stream)313 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
314   InputAt(0)->PrintTo(stream);
315   stream->Add("[%d] <- ", slot_index());
316   InputAt(1)->PrintTo(stream);
317 }
318 
319 
PrintDataTo(StringStream * stream)320 void LInvokeFunction::PrintDataTo(StringStream* stream) {
321   stream->Add("= ");
322   InputAt(0)->PrintTo(stream);
323   stream->Add(" ");
324   InputAt(1)->PrintTo(stream);
325   stream->Add(" #%d / ", arity());
326 }
327 
328 
PrintDataTo(StringStream * stream)329 void LCallKeyed::PrintDataTo(StringStream* stream) {
330   stream->Add("[ecx] #%d / ", arity());
331 }
332 
333 
PrintDataTo(StringStream * stream)334 void LCallNamed::PrintDataTo(StringStream* stream) {
335   SmartArrayPointer<char> name_string = name()->ToCString();
336   stream->Add("%s #%d / ", *name_string, arity());
337 }
338 
339 
PrintDataTo(StringStream * stream)340 void LCallGlobal::PrintDataTo(StringStream* stream) {
341   SmartArrayPointer<char> name_string = name()->ToCString();
342   stream->Add("%s #%d / ", *name_string, arity());
343 }
344 
345 
PrintDataTo(StringStream * stream)346 void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
347   stream->Add("#%d / ", arity());
348 }
349 
350 
PrintDataTo(StringStream * stream)351 void LCallNew::PrintDataTo(StringStream* stream) {
352   stream->Add("= ");
353   InputAt(0)->PrintTo(stream);
354   stream->Add(" #%d / ", arity());
355 }
356 
357 
PrintDataTo(StringStream * stream)358 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
359   arguments()->PrintTo(stream);
360 
361   stream->Add(" length ");
362   length()->PrintTo(stream);
363 
364   stream->Add(" index ");
365   index()->PrintTo(stream);
366 }
367 
368 
GetNextSpillIndex(bool is_double)369 int LChunk::GetNextSpillIndex(bool is_double) {
370   // Skip a slot if for a double-width slot.
371   if (is_double) spill_slot_count_++;
372   return spill_slot_count_++;
373 }
374 
375 
GetNextSpillSlot(bool is_double)376 LOperand* LChunk::GetNextSpillSlot(bool is_double) {
377   int index = GetNextSpillIndex(is_double);
378   if (is_double) {
379     return LDoubleStackSlot::Create(index);
380   } else {
381     return LStackSlot::Create(index);
382   }
383 }
384 
385 
MarkEmptyBlocks()386 void LChunk::MarkEmptyBlocks() {
387   HPhase phase("L_Mark empty blocks", this);
388   for (int i = 0; i < graph()->blocks()->length(); ++i) {
389     HBasicBlock* block = graph()->blocks()->at(i);
390     int first = block->first_instruction_index();
391     int last = block->last_instruction_index();
392     LInstruction* first_instr = instructions()->at(first);
393     LInstruction* last_instr = instructions()->at(last);
394 
395     LLabel* label = LLabel::cast(first_instr);
396     if (last_instr->IsGoto()) {
397       LGoto* goto_instr = LGoto::cast(last_instr);
398       if (label->IsRedundant() &&
399           !label->is_loop_header()) {
400         bool can_eliminate = true;
401         for (int i = first + 1; i < last && can_eliminate; ++i) {
402           LInstruction* cur = instructions()->at(i);
403           if (cur->IsGap()) {
404             LGap* gap = LGap::cast(cur);
405             if (!gap->IsRedundant()) {
406               can_eliminate = false;
407             }
408           } else {
409             can_eliminate = false;
410           }
411         }
412 
413         if (can_eliminate) {
414           label->set_replacement(GetLabel(goto_instr->block_id()));
415         }
416       }
417     }
418   }
419 }
420 
421 
PrintDataTo(StringStream * stream)422 void LStoreNamedField::PrintDataTo(StringStream* stream) {
423   object()->PrintTo(stream);
424   stream->Add(".");
425   stream->Add(*String::cast(*name())->ToCString());
426   stream->Add(" <- ");
427   value()->PrintTo(stream);
428 }
429 
430 
PrintDataTo(StringStream * stream)431 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
432   object()->PrintTo(stream);
433   stream->Add(".");
434   stream->Add(*String::cast(*name())->ToCString());
435   stream->Add(" <- ");
436   value()->PrintTo(stream);
437 }
438 
439 
PrintDataTo(StringStream * stream)440 void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
441   object()->PrintTo(stream);
442   stream->Add("[");
443   key()->PrintTo(stream);
444   stream->Add("] <- ");
445   value()->PrintTo(stream);
446 }
447 
448 
PrintDataTo(StringStream * stream)449 void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
450   elements()->PrintTo(stream);
451   stream->Add("[");
452   key()->PrintTo(stream);
453   stream->Add("] <- ");
454   value()->PrintTo(stream);
455 }
456 
457 
PrintDataTo(StringStream * stream)458 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
459   object()->PrintTo(stream);
460   stream->Add("[");
461   key()->PrintTo(stream);
462   stream->Add("] <- ");
463   value()->PrintTo(stream);
464 }
465 
466 
PrintDataTo(StringStream * stream)467 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
468   object()->PrintTo(stream);
469   stream->Add(" %p -> %p", *original_map(), *transitioned_map());
470 }
471 
472 
AddInstruction(LInstruction * instr,HBasicBlock * block)473 void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
474   LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
475   int index = -1;
476   if (instr->IsControl()) {
477     instructions_.Add(gap);
478     index = instructions_.length();
479     instructions_.Add(instr);
480   } else {
481     index = instructions_.length();
482     instructions_.Add(instr);
483     instructions_.Add(gap);
484   }
485   if (instr->HasPointerMap()) {
486     pointer_maps_.Add(instr->pointer_map());
487     instr->pointer_map()->set_lithium_position(index);
488   }
489 }
490 
491 
DefineConstantOperand(HConstant * constant)492 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
493   return LConstantOperand::Create(constant->id());
494 }
495 
496 
GetParameterStackSlot(int index) const497 int LChunk::GetParameterStackSlot(int index) const {
498   // The receiver is at index 0, the first parameter at index 1, so we
499   // shift all parameter indexes down by the number of parameters, and
500   // make sure they end up negative so they are distinguishable from
501   // spill slots.
502   int result = index - info()->scope()->num_parameters() - 1;
503   ASSERT(result < 0);
504   return result;
505 }
506 
507 // A parameter relative to ebp in the arguments stub.
ParameterAt(int index)508 int LChunk::ParameterAt(int index) {
509   ASSERT(-1 <= index);  // -1 is the receiver.
510   return (1 + info()->scope()->num_parameters() - index) *
511       kPointerSize;
512 }
513 
514 
GetGapAt(int index) const515 LGap* LChunk::GetGapAt(int index) const {
516   return LGap::cast(instructions_[index]);
517 }
518 
519 
IsGapAt(int index) const520 bool LChunk::IsGapAt(int index) const {
521   return instructions_[index]->IsGap();
522 }
523 
524 
NearestGapPos(int index) const525 int LChunk::NearestGapPos(int index) const {
526   while (!IsGapAt(index)) index--;
527   return index;
528 }
529 
530 
AddGapMove(int index,LOperand * from,LOperand * to)531 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
532   GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
533 }
534 
535 
LookupLiteral(LConstantOperand * operand) const536 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
537   return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
538 }
539 
540 
LookupLiteralRepresentation(LConstantOperand * operand) const541 Representation LChunk::LookupLiteralRepresentation(
542     LConstantOperand* operand) const {
543   return graph_->LookupValue(operand->index())->representation();
544 }
545 
546 
Build()547 LChunk* LChunkBuilder::Build() {
548   ASSERT(is_unused());
549   chunk_ = new(zone()) LChunk(info(), graph());
550   HPhase phase("L_Building chunk", chunk_);
551   status_ = BUILDING;
552   const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
553   for (int i = 0; i < blocks->length(); i++) {
554     HBasicBlock* next = NULL;
555     if (i < blocks->length() - 1) next = blocks->at(i + 1);
556     DoBasicBlock(blocks->at(i), next);
557     if (is_aborted()) return NULL;
558   }
559   status_ = DONE;
560   return chunk_;
561 }
562 
563 
Abort(const char * format,...)564 void LChunkBuilder::Abort(const char* format, ...) {
565   if (FLAG_trace_bailout) {
566     SmartArrayPointer<char> name(
567         info()->shared_info()->DebugName()->ToCString());
568     PrintF("Aborting LChunk building in @\"%s\": ", *name);
569     va_list arguments;
570     va_start(arguments, format);
571     OS::VPrint(format, arguments);
572     va_end(arguments);
573     PrintF("\n");
574   }
575   status_ = ABORTED;
576 }
577 
578 
ToUnallocated(Register reg)579 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
580   return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
581                                   Register::ToAllocationIndex(reg));
582 }
583 
584 
ToUnallocated(XMMRegister reg)585 LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
586   return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
587                                   XMMRegister::ToAllocationIndex(reg));
588 }
589 
590 
UseFixed(HValue * value,Register fixed_register)591 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
592   return Use(value, ToUnallocated(fixed_register));
593 }
594 
595 
UseFixedDouble(HValue * value,XMMRegister reg)596 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
597   return Use(value, ToUnallocated(reg));
598 }
599 
600 
UseRegister(HValue * value)601 LOperand* LChunkBuilder::UseRegister(HValue* value) {
602   return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
603 }
604 
605 
UseRegisterAtStart(HValue * value)606 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
607   return Use(value,
608              new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
609                                       LUnallocated::USED_AT_START));
610 }
611 
612 
UseTempRegister(HValue * value)613 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
614   return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
615 }
616 
617 
Use(HValue * value)618 LOperand* LChunkBuilder::Use(HValue* value) {
619   return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
620 }
621 
622 
UseAtStart(HValue * value)623 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
624   return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
625                                              LUnallocated::USED_AT_START));
626 }
627 
628 
UseOrConstant(HValue * value)629 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
630   return value->IsConstant()
631       ? chunk_->DefineConstantOperand(HConstant::cast(value))
632       : Use(value);
633 }
634 
635 
UseOrConstantAtStart(HValue * value)636 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
637   return value->IsConstant()
638       ? chunk_->DefineConstantOperand(HConstant::cast(value))
639       : UseAtStart(value);
640 }
641 
642 
UseRegisterOrConstant(HValue * value)643 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
644   return value->IsConstant()
645       ? chunk_->DefineConstantOperand(HConstant::cast(value))
646       : UseRegister(value);
647 }
648 
649 
UseRegisterOrConstantAtStart(HValue * value)650 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
651   return value->IsConstant()
652       ? chunk_->DefineConstantOperand(HConstant::cast(value))
653       : UseRegisterAtStart(value);
654 }
655 
656 
UseAny(HValue * value)657 LOperand* LChunkBuilder::UseAny(HValue* value) {
658   return value->IsConstant()
659       ? chunk_->DefineConstantOperand(HConstant::cast(value))
660       :  Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
661 }
662 
663 
Use(HValue * value,LUnallocated * operand)664 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
665   if (value->EmitAtUses()) {
666     HInstruction* instr = HInstruction::cast(value);
667     VisitInstruction(instr);
668   }
669   operand->set_virtual_register(value->id());
670   return operand;
671 }
672 
673 
674 template<int I, int T>
Define(LTemplateInstruction<1,I,T> * instr,LUnallocated * result)675 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
676                                     LUnallocated* result) {
677   result->set_virtual_register(current_instruction_->id());
678   instr->set_result(result);
679   return instr;
680 }
681 
682 
683 template<int I, int T>
DefineAsRegister(LTemplateInstruction<1,I,T> * instr)684 LInstruction* LChunkBuilder::DefineAsRegister(
685     LTemplateInstruction<1, I, T>* instr) {
686   return Define(instr,
687                 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
688 }
689 
690 
691 template<int I, int T>
DefineAsSpilled(LTemplateInstruction<1,I,T> * instr,int index)692 LInstruction* LChunkBuilder::DefineAsSpilled(
693     LTemplateInstruction<1, I, T>* instr,
694     int index) {
695   return Define(instr,
696                 new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
697 }
698 
699 
700 template<int I, int T>
DefineSameAsFirst(LTemplateInstruction<1,I,T> * instr)701 LInstruction* LChunkBuilder::DefineSameAsFirst(
702     LTemplateInstruction<1, I, T>* instr) {
703   return Define(instr,
704                 new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
705 }
706 
707 
708 template<int I, int T>
DefineFixed(LTemplateInstruction<1,I,T> * instr,Register reg)709 LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
710                                          Register reg) {
711   return Define(instr, ToUnallocated(reg));
712 }
713 
714 
715 template<int I, int T>
DefineFixedDouble(LTemplateInstruction<1,I,T> * instr,XMMRegister reg)716 LInstruction* LChunkBuilder::DefineFixedDouble(
717     LTemplateInstruction<1, I, T>* instr,
718     XMMRegister reg) {
719   return Define(instr, ToUnallocated(reg));
720 }
721 
722 
AssignEnvironment(LInstruction * instr)723 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
724   HEnvironment* hydrogen_env = current_block_->last_environment();
725   int argument_index_accumulator = 0;
726   instr->set_environment(CreateEnvironment(hydrogen_env,
727                                            &argument_index_accumulator));
728   return instr;
729 }
730 
731 
SetInstructionPendingDeoptimizationEnvironment(LInstruction * instr,int ast_id)732 LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
733     LInstruction* instr, int ast_id) {
734   ASSERT(instruction_pending_deoptimization_environment_ == NULL);
735   ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
736   instruction_pending_deoptimization_environment_ = instr;
737   pending_deoptimization_ast_id_ = ast_id;
738   return instr;
739 }
740 
741 
ClearInstructionPendingDeoptimizationEnvironment()742 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
743   instruction_pending_deoptimization_environment_ = NULL;
744   pending_deoptimization_ast_id_ = AstNode::kNoNumber;
745 }
746 
747 
MarkAsCall(LInstruction * instr,HInstruction * hinstr,CanDeoptimize can_deoptimize)748 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
749                                         HInstruction* hinstr,
750                                         CanDeoptimize can_deoptimize) {
751 #ifdef DEBUG
752   instr->VerifyCall();
753 #endif
754   instr->MarkAsCall();
755   instr = AssignPointerMap(instr);
756 
757   if (hinstr->HasObservableSideEffects()) {
758     ASSERT(hinstr->next()->IsSimulate());
759     HSimulate* sim = HSimulate::cast(hinstr->next());
760     instr = SetInstructionPendingDeoptimizationEnvironment(
761         instr, sim->ast_id());
762   }
763 
764   // If instruction does not have side-effects lazy deoptimization
765   // after the call will try to deoptimize to the point before the call.
766   // Thus we still need to attach environment to this call even if
767   // call sequence can not deoptimize eagerly.
768   bool needs_environment =
769       (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
770       !hinstr->HasObservableSideEffects();
771   if (needs_environment && !instr->HasEnvironment()) {
772     instr = AssignEnvironment(instr);
773   }
774 
775   return instr;
776 }
777 
778 
MarkAsSaveDoubles(LInstruction * instr)779 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
780   instr->MarkAsSaveDoubles();
781   return instr;
782 }
783 
784 
AssignPointerMap(LInstruction * instr)785 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
786   ASSERT(!instr->HasPointerMap());
787   instr->set_pointer_map(new(zone()) LPointerMap(position_));
788   return instr;
789 }
790 
791 
TempRegister()792 LUnallocated* LChunkBuilder::TempRegister() {
793   LUnallocated* operand =
794       new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
795   operand->set_virtual_register(allocator_->GetVirtualRegister());
796   if (!allocator_->AllocationOk()) {
797     Abort("Not enough virtual registers (temps).");
798   }
799   return operand;
800 }
801 
802 
FixedTemp(Register reg)803 LOperand* LChunkBuilder::FixedTemp(Register reg) {
804   LUnallocated* operand = ToUnallocated(reg);
805   ASSERT(operand->HasFixedPolicy());
806   return operand;
807 }
808 
809 
FixedTemp(XMMRegister reg)810 LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
811   LUnallocated* operand = ToUnallocated(reg);
812   ASSERT(operand->HasFixedPolicy());
813   return operand;
814 }
815 
816 
DoBlockEntry(HBlockEntry * instr)817 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
818   return new(zone()) LLabel(instr->block());
819 }
820 
821 
DoSoftDeoptimize(HSoftDeoptimize * instr)822 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
823   return AssignEnvironment(new(zone()) LDeoptimize);
824 }
825 
826 
DoDeoptimize(HDeoptimize * instr)827 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
828   return AssignEnvironment(new(zone()) LDeoptimize);
829 }
830 
831 
DoShift(Token::Value op,HBitwiseBinaryOperation * instr)832 LInstruction* LChunkBuilder::DoShift(Token::Value op,
833                                      HBitwiseBinaryOperation* instr) {
834   if (instr->representation().IsTagged()) {
835     ASSERT(instr->left()->representation().IsTagged());
836     ASSERT(instr->right()->representation().IsTagged());
837 
838     LOperand* context = UseFixed(instr->context(), esi);
839     LOperand* left = UseFixed(instr->left(), edx);
840     LOperand* right = UseFixed(instr->right(), eax);
841     LArithmeticT* result = new(zone()) LArithmeticT(op, context, left, right);
842     return MarkAsCall(DefineFixed(result, eax), instr);
843   }
844 
845   ASSERT(instr->representation().IsInteger32());
846   ASSERT(instr->left()->representation().IsInteger32());
847   ASSERT(instr->right()->representation().IsInteger32());
848   LOperand* left = UseRegisterAtStart(instr->left());
849 
850   HValue* right_value = instr->right();
851   LOperand* right = NULL;
852   int constant_value = 0;
853   if (right_value->IsConstant()) {
854     HConstant* constant = HConstant::cast(right_value);
855     right = chunk_->DefineConstantOperand(constant);
856     constant_value = constant->Integer32Value() & 0x1f;
857   } else {
858     right = UseFixed(right_value, ecx);
859   }
860 
861   // Shift operations can only deoptimize if we do a logical shift by 0 and
862   // the result cannot be truncated to int32.
863   bool may_deopt = (op == Token::SHR && constant_value == 0);
864   bool does_deopt = false;
865   if (may_deopt) {
866     for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
867       if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
868         does_deopt = true;
869         break;
870       }
871     }
872   }
873 
874   LInstruction* result =
875       DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
876   return does_deopt ? AssignEnvironment(result) : result;
877 }
878 
879 
DoArithmeticD(Token::Value op,HArithmeticBinaryOperation * instr)880 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
881                                            HArithmeticBinaryOperation* instr) {
882   ASSERT(instr->representation().IsDouble());
883   ASSERT(instr->left()->representation().IsDouble());
884   ASSERT(instr->right()->representation().IsDouble());
885   ASSERT(op != Token::MOD);
886   LOperand* left = UseRegisterAtStart(instr->left());
887   LOperand* right = UseRegisterAtStart(instr->right());
888   LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
889   return DefineSameAsFirst(result);
890 }
891 
892 
DoArithmeticT(Token::Value op,HArithmeticBinaryOperation * instr)893 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
894                                            HArithmeticBinaryOperation* instr) {
895   ASSERT(op == Token::ADD ||
896          op == Token::DIV ||
897          op == Token::MOD ||
898          op == Token::MUL ||
899          op == Token::SUB);
900   HValue* left = instr->left();
901   HValue* right = instr->right();
902   ASSERT(left->representation().IsTagged());
903   ASSERT(right->representation().IsTagged());
904   LOperand* context = UseFixed(instr->context(), esi);
905   LOperand* left_operand = UseFixed(left, edx);
906   LOperand* right_operand = UseFixed(right, eax);
907   LArithmeticT* result =
908       new(zone()) LArithmeticT(op, context, left_operand, right_operand);
909   return MarkAsCall(DefineFixed(result, eax), instr);
910 }
911 
912 
DoBasicBlock(HBasicBlock * block,HBasicBlock * next_block)913 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
914   ASSERT(is_building());
915   current_block_ = block;
916   next_block_ = next_block;
917   if (block->IsStartBlock()) {
918     block->UpdateEnvironment(graph_->start_environment());
919     argument_count_ = 0;
920   } else if (block->predecessors()->length() == 1) {
921     // We have a single predecessor => copy environment and outgoing
922     // argument count from the predecessor.
923     ASSERT(block->phis()->length() == 0);
924     HBasicBlock* pred = block->predecessors()->at(0);
925     HEnvironment* last_environment = pred->last_environment();
926     ASSERT(last_environment != NULL);
927     // Only copy the environment, if it is later used again.
928     if (pred->end()->SecondSuccessor() == NULL) {
929       ASSERT(pred->end()->FirstSuccessor() == block);
930     } else {
931       if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
932           pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
933         last_environment = last_environment->Copy();
934       }
935     }
936     block->UpdateEnvironment(last_environment);
937     ASSERT(pred->argument_count() >= 0);
938     argument_count_ = pred->argument_count();
939   } else {
940     // We are at a state join => process phis.
941     HBasicBlock* pred = block->predecessors()->at(0);
942     // No need to copy the environment, it cannot be used later.
943     HEnvironment* last_environment = pred->last_environment();
944     for (int i = 0; i < block->phis()->length(); ++i) {
945       HPhi* phi = block->phis()->at(i);
946       last_environment->SetValueAt(phi->merged_index(), phi);
947     }
948     for (int i = 0; i < block->deleted_phis()->length(); ++i) {
949       last_environment->SetValueAt(block->deleted_phis()->at(i),
950                                    graph_->GetConstantUndefined());
951     }
952     block->UpdateEnvironment(last_environment);
953     // Pick up the outgoing argument count of one of the predecessors.
954     argument_count_ = pred->argument_count();
955   }
956   HInstruction* current = block->first();
957   int start = chunk_->instructions()->length();
958   while (current != NULL && !is_aborted()) {
959     // Code for constants in registers is generated lazily.
960     if (!current->EmitAtUses()) {
961       VisitInstruction(current);
962     }
963     current = current->next();
964   }
965   int end = chunk_->instructions()->length() - 1;
966   if (end >= start) {
967     block->set_first_instruction_index(start);
968     block->set_last_instruction_index(end);
969   }
970   block->set_argument_count(argument_count_);
971   next_block_ = NULL;
972   current_block_ = NULL;
973 }
974 
975 
VisitInstruction(HInstruction * current)976 void LChunkBuilder::VisitInstruction(HInstruction* current) {
977   HInstruction* old_current = current_instruction_;
978   current_instruction_ = current;
979   if (current->has_position()) position_ = current->position();
980   LInstruction* instr = current->CompileToLithium(this);
981 
982   if (instr != NULL) {
983     if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
984       instr = AssignPointerMap(instr);
985     }
986     if (FLAG_stress_environments && !instr->HasEnvironment()) {
987       instr = AssignEnvironment(instr);
988     }
989     instr->set_hydrogen_value(current);
990     chunk_->AddInstruction(instr, current_block_);
991   }
992   current_instruction_ = old_current;
993 }
994 
995 
CreateEnvironment(HEnvironment * hydrogen_env,int * argument_index_accumulator)996 LEnvironment* LChunkBuilder::CreateEnvironment(
997     HEnvironment* hydrogen_env,
998     int* argument_index_accumulator) {
999   if (hydrogen_env == NULL) return NULL;
1000 
1001   LEnvironment* outer =
1002       CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
1003   int ast_id = hydrogen_env->ast_id();
1004   ASSERT(ast_id != AstNode::kNoNumber ||
1005          hydrogen_env->frame_type() != JS_FUNCTION);
1006   int value_count = hydrogen_env->length();
1007   LEnvironment* result =
1008       new(zone()) LEnvironment(hydrogen_env->closure(),
1009                                hydrogen_env->frame_type(),
1010                                ast_id,
1011                                hydrogen_env->parameter_count(),
1012                                argument_count_,
1013                                value_count,
1014                                outer);
1015   int argument_index = *argument_index_accumulator;
1016   for (int i = 0; i < value_count; ++i) {
1017     if (hydrogen_env->is_special_index(i)) continue;
1018 
1019     HValue* value = hydrogen_env->values()->at(i);
1020     LOperand* op = NULL;
1021     if (value->IsArgumentsObject()) {
1022       op = NULL;
1023     } else if (value->IsPushArgument()) {
1024       op = new(zone()) LArgument(argument_index++);
1025     } else {
1026       op = UseAny(value);
1027     }
1028     result->AddValue(op, value->representation());
1029   }
1030 
1031   if (hydrogen_env->frame_type() == JS_FUNCTION) {
1032     *argument_index_accumulator = argument_index;
1033   }
1034 
1035   return result;
1036 }
1037 
1038 
DoGoto(HGoto * instr)1039 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1040   return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
1041 }
1042 
1043 
DoBranch(HBranch * instr)1044 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
1045   HValue* value = instr->value();
1046   if (value->EmitAtUses()) {
1047     ASSERT(value->IsConstant());
1048     ASSERT(!value->representation().IsDouble());
1049     HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
1050         ? instr->FirstSuccessor()
1051         : instr->SecondSuccessor();
1052     return new(zone()) LGoto(successor->block_id());
1053   }
1054 
1055   // Untagged integers or doubles, smis and booleans don't require a
1056   // deoptimization environment nor a temp register.
1057   Representation rep = value->representation();
1058   HType type = value->type();
1059   if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) {
1060     return new(zone()) LBranch(UseRegister(value), NULL);
1061   }
1062 
1063   ToBooleanStub::Types expected = instr->expected_input_types();
1064   // We need a temporary register when we have to access the map *or* we have
1065   // no type info yet, in which case we handle all cases (including the ones
1066   // involving maps).
1067   bool needs_temp = expected.NeedsMap() || expected.IsEmpty();
1068   LOperand* temp = needs_temp ? TempRegister() : NULL;
1069   return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp));
1070 }
1071 
1072 
DoCompareMap(HCompareMap * instr)1073 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
1074   ASSERT(instr->value()->representation().IsTagged());
1075   LOperand* value = UseRegisterAtStart(instr->value());
1076   return new(zone()) LCmpMapAndBranch(value);
1077 }
1078 
1079 
DoArgumentsLength(HArgumentsLength * length)1080 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
1081   return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
1082 }
1083 
1084 
DoArgumentsElements(HArgumentsElements * elems)1085 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1086   return DefineAsRegister(new(zone()) LArgumentsElements);
1087 }
1088 
1089 
DoInstanceOf(HInstanceOf * instr)1090 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1091   LOperand* left = UseFixed(instr->left(), InstanceofStub::left());
1092   LOperand* right = UseFixed(instr->right(), InstanceofStub::right());
1093   LOperand* context = UseFixed(instr->context(), esi);
1094   LInstanceOf* result = new(zone()) LInstanceOf(context, left, right);
1095   return MarkAsCall(DefineFixed(result, eax), instr);
1096 }
1097 
1098 
DoInstanceOfKnownGlobal(HInstanceOfKnownGlobal * instr)1099 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1100     HInstanceOfKnownGlobal* instr) {
1101   LInstanceOfKnownGlobal* result =
1102       new(zone()) LInstanceOfKnownGlobal(
1103           UseFixed(instr->context(), esi),
1104           UseFixed(instr->left(), InstanceofStub::left()),
1105           FixedTemp(edi));
1106   return MarkAsCall(DefineFixed(result, eax), instr);
1107 }
1108 
1109 
DoWrapReceiver(HWrapReceiver * instr)1110 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1111   LOperand* receiver = UseRegister(instr->receiver());
1112   LOperand* function = UseRegisterAtStart(instr->function());
1113   LOperand* temp = TempRegister();
1114   LWrapReceiver* result =
1115       new(zone()) LWrapReceiver(receiver, function, temp);
1116   return AssignEnvironment(DefineSameAsFirst(result));
1117 }
1118 
1119 
DoApplyArguments(HApplyArguments * instr)1120 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1121   LOperand* function = UseFixed(instr->function(), edi);
1122   LOperand* receiver = UseFixed(instr->receiver(), eax);
1123   LOperand* length = UseFixed(instr->length(), ebx);
1124   LOperand* elements = UseFixed(instr->elements(), ecx);
1125   LApplyArguments* result = new(zone()) LApplyArguments(function,
1126                                                         receiver,
1127                                                         length,
1128                                                         elements);
1129   return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1130 }
1131 
1132 
DoPushArgument(HPushArgument * instr)1133 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1134   ++argument_count_;
1135   LOperand* argument = UseAny(instr->argument());
1136   return new(zone()) LPushArgument(argument);
1137 }
1138 
1139 
DoThisFunction(HThisFunction * instr)1140 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1141   return instr->HasNoUses()
1142       ? NULL
1143       : DefineAsRegister(new(zone()) LThisFunction);
1144 }
1145 
1146 
DoContext(HContext * instr)1147 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1148   return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
1149 }
1150 
1151 
DoOuterContext(HOuterContext * instr)1152 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1153   LOperand* context = UseRegisterAtStart(instr->value());
1154   return DefineAsRegister(new(zone()) LOuterContext(context));
1155 }
1156 
1157 
DoDeclareGlobals(HDeclareGlobals * instr)1158 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1159   LOperand* context = UseFixed(instr->context(), esi);
1160   return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
1161 }
1162 
1163 
DoGlobalObject(HGlobalObject * instr)1164 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1165   LOperand* context = UseRegisterAtStart(instr->value());
1166   return DefineAsRegister(new(zone()) LGlobalObject(context));
1167 }
1168 
1169 
DoGlobalReceiver(HGlobalReceiver * instr)1170 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1171   LOperand* global_object = UseRegisterAtStart(instr->value());
1172   return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
1173 }
1174 
1175 
DoCallConstantFunction(HCallConstantFunction * instr)1176 LInstruction* LChunkBuilder::DoCallConstantFunction(
1177     HCallConstantFunction* instr) {
1178   argument_count_ -= instr->argument_count();
1179   return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, eax), instr);
1180 }
1181 
1182 
DoInvokeFunction(HInvokeFunction * instr)1183 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1184   LOperand* context = UseFixed(instr->context(), esi);
1185   LOperand* function = UseFixed(instr->function(), edi);
1186   argument_count_ -= instr->argument_count();
1187   LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
1188   return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1189 }
1190 
1191 
DoUnaryMathOperation(HUnaryMathOperation * instr)1192 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1193   BuiltinFunctionId op = instr->op();
1194   if (op == kMathLog) {
1195     ASSERT(instr->representation().IsDouble());
1196     ASSERT(instr->value()->representation().IsDouble());
1197     LOperand* context = UseAny(instr->context());  // Not actually used.
1198     LOperand* input = UseRegisterAtStart(instr->value());
1199     LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context,
1200                                                                   input);
1201     return DefineSameAsFirst(result);
1202   } else if (op == kMathSin || op == kMathCos || op == kMathTan) {
1203     LOperand* context = UseFixed(instr->context(), esi);
1204     LOperand* input = UseFixedDouble(instr->value(), xmm1);
1205     LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context,
1206                                                                   input);
1207     return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1208   } else {
1209     LOperand* input = UseRegisterAtStart(instr->value());
1210     LOperand* context = UseAny(instr->context());  // Deferred use by MathAbs.
1211     if (op == kMathPowHalf) {
1212       LOperand* temp = TempRegister();
1213       LMathPowHalf* result = new(zone()) LMathPowHalf(context, input, temp);
1214       return DefineSameAsFirst(result);
1215     }
1216     LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context,
1217                                                                   input);
1218     switch (op) {
1219       case kMathAbs:
1220         return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1221       case kMathFloor:
1222         return AssignEnvironment(DefineAsRegister(result));
1223       case kMathRound:
1224         return AssignEnvironment(DefineAsRegister(result));
1225       case kMathSqrt:
1226         return DefineSameAsFirst(result);
1227       default:
1228         UNREACHABLE();
1229         return NULL;
1230     }
1231   }
1232 }
1233 
1234 
DoCallKeyed(HCallKeyed * instr)1235 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1236   ASSERT(instr->key()->representation().IsTagged());
1237   LOperand* context = UseFixed(instr->context(), esi);
1238   LOperand* key = UseFixed(instr->key(), ecx);
1239   argument_count_ -= instr->argument_count();
1240   LCallKeyed* result = new(zone()) LCallKeyed(context, key);
1241   return MarkAsCall(DefineFixed(result, eax), instr);
1242 }
1243 
1244 
DoCallNamed(HCallNamed * instr)1245 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1246   LOperand* context = UseFixed(instr->context(), esi);
1247   argument_count_ -= instr->argument_count();
1248   LCallNamed* result = new(zone()) LCallNamed(context);
1249   return MarkAsCall(DefineFixed(result, eax), instr);
1250 }
1251 
1252 
DoCallGlobal(HCallGlobal * instr)1253 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1254   LOperand* context = UseFixed(instr->context(), esi);
1255   argument_count_ -= instr->argument_count();
1256   LCallGlobal* result = new(zone()) LCallGlobal(context);
1257   return MarkAsCall(DefineFixed(result, eax), instr);
1258 }
1259 
1260 
DoCallKnownGlobal(HCallKnownGlobal * instr)1261 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1262   argument_count_ -= instr->argument_count();
1263   return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, eax), instr);
1264 }
1265 
1266 
DoCallNew(HCallNew * instr)1267 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1268   LOperand* context = UseFixed(instr->context(), esi);
1269   LOperand* constructor = UseFixed(instr->constructor(), edi);
1270   argument_count_ -= instr->argument_count();
1271   LCallNew* result = new(zone()) LCallNew(context, constructor);
1272   return MarkAsCall(DefineFixed(result, eax), instr);
1273 }
1274 
1275 
DoCallFunction(HCallFunction * instr)1276 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1277   LOperand* context = UseFixed(instr->context(), esi);
1278   LOperand* function = UseFixed(instr->function(), edi);
1279   argument_count_ -= instr->argument_count();
1280   LCallFunction* result = new(zone()) LCallFunction(context, function);
1281   return MarkAsCall(DefineFixed(result, eax), instr);
1282 }
1283 
1284 
DoCallRuntime(HCallRuntime * instr)1285 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1286   argument_count_ -= instr->argument_count();
1287   LOperand* context = UseFixed(instr->context(), esi);
1288   return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr);
1289 }
1290 
1291 
DoShr(HShr * instr)1292 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1293   return DoShift(Token::SHR, instr);
1294 }
1295 
1296 
DoSar(HSar * instr)1297 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1298   return DoShift(Token::SAR, instr);
1299 }
1300 
1301 
DoShl(HShl * instr)1302 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1303   return DoShift(Token::SHL, instr);
1304 }
1305 
1306 
DoBitwise(HBitwise * instr)1307 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1308   if (instr->representation().IsInteger32()) {
1309     ASSERT(instr->left()->representation().IsInteger32());
1310     ASSERT(instr->right()->representation().IsInteger32());
1311 
1312     LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1313     LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1314     return DefineSameAsFirst(new(zone()) LBitI(left, right));
1315   } else {
1316     ASSERT(instr->representation().IsTagged());
1317     ASSERT(instr->left()->representation().IsTagged());
1318     ASSERT(instr->right()->representation().IsTagged());
1319 
1320     LOperand* context = UseFixed(instr->context(), esi);
1321     LOperand* left = UseFixed(instr->left(), edx);
1322     LOperand* right = UseFixed(instr->right(), eax);
1323     LArithmeticT* result =
1324         new(zone()) LArithmeticT(instr->op(), context, left, right);
1325     return MarkAsCall(DefineFixed(result, eax), instr);
1326   }
1327 }
1328 
1329 
DoBitNot(HBitNot * instr)1330 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1331   ASSERT(instr->value()->representation().IsInteger32());
1332   ASSERT(instr->representation().IsInteger32());
1333   LOperand* input = UseRegisterAtStart(instr->value());
1334   LBitNotI* result = new(zone()) LBitNotI(input);
1335   return DefineSameAsFirst(result);
1336 }
1337 
1338 
DoDiv(HDiv * instr)1339 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1340   if (instr->representation().IsDouble()) {
1341     return DoArithmeticD(Token::DIV, instr);
1342   } else if (instr->representation().IsInteger32()) {
1343     // The temporary operand is necessary to ensure that right is not allocated
1344     // into edx.
1345     LOperand* temp = FixedTemp(edx);
1346     LOperand* dividend = UseFixed(instr->left(), eax);
1347     LOperand* divisor = UseRegister(instr->right());
1348     LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
1349     return AssignEnvironment(DefineFixed(result, eax));
1350   } else {
1351     ASSERT(instr->representation().IsTagged());
1352     return DoArithmeticT(Token::DIV, instr);
1353   }
1354 }
1355 
1356 
DoMod(HMod * instr)1357 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1358   if (instr->representation().IsInteger32()) {
1359     ASSERT(instr->left()->representation().IsInteger32());
1360     ASSERT(instr->right()->representation().IsInteger32());
1361 
1362     LInstruction* result;
1363     if (instr->HasPowerOf2Divisor()) {
1364       ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1365       LOperand* value = UseRegisterAtStart(instr->left());
1366       LModI* mod =
1367           new(zone()) LModI(value, UseOrConstant(instr->right()), NULL);
1368       result = DefineSameAsFirst(mod);
1369     } else {
1370       // The temporary operand is necessary to ensure that right is
1371       // not allocated into edx.
1372       LOperand* temp = FixedTemp(edx);
1373       LOperand* value = UseFixed(instr->left(), eax);
1374       LOperand* divisor = UseRegister(instr->right());
1375       LModI* mod = new(zone()) LModI(value, divisor, temp);
1376       result = DefineFixed(mod, edx);
1377     }
1378 
1379     return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1380             instr->CheckFlag(HValue::kCanBeDivByZero))
1381         ? AssignEnvironment(result)
1382         : result;
1383   } else if (instr->representation().IsTagged()) {
1384     return DoArithmeticT(Token::MOD, instr);
1385   } else {
1386     ASSERT(instr->representation().IsDouble());
1387     // We call a C function for double modulo. It can't trigger a GC.
1388     // We need to use fixed result register for the call.
1389     // TODO(fschneider): Allow any register as input registers.
1390     LOperand* left = UseFixedDouble(instr->left(), xmm2);
1391     LOperand* right = UseFixedDouble(instr->right(), xmm1);
1392     LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
1393     return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1394   }
1395 }
1396 
1397 
DoMul(HMul * instr)1398 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1399   if (instr->representation().IsInteger32()) {
1400     ASSERT(instr->left()->representation().IsInteger32());
1401     ASSERT(instr->right()->representation().IsInteger32());
1402     LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1403     LOperand* right = UseOrConstant(instr->MostConstantOperand());
1404     LOperand* temp = NULL;
1405     if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1406       temp = TempRegister();
1407     }
1408     LMulI* mul = new(zone()) LMulI(left, right, temp);
1409     if (instr->CheckFlag(HValue::kCanOverflow) ||
1410         instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1411       AssignEnvironment(mul);
1412     }
1413     return DefineSameAsFirst(mul);
1414   } else if (instr->representation().IsDouble()) {
1415     return DoArithmeticD(Token::MUL, instr);
1416   } else {
1417     ASSERT(instr->representation().IsTagged());
1418     return DoArithmeticT(Token::MUL, instr);
1419   }
1420 }
1421 
1422 
DoSub(HSub * instr)1423 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1424   if (instr->representation().IsInteger32()) {
1425     ASSERT(instr->left()->representation().IsInteger32());
1426     ASSERT(instr->right()->representation().IsInteger32());
1427     LOperand* left = UseRegisterAtStart(instr->left());
1428     LOperand* right = UseOrConstantAtStart(instr->right());
1429     LSubI* sub = new(zone()) LSubI(left, right);
1430     LInstruction* result = DefineSameAsFirst(sub);
1431     if (instr->CheckFlag(HValue::kCanOverflow)) {
1432       result = AssignEnvironment(result);
1433     }
1434     return result;
1435   } else if (instr->representation().IsDouble()) {
1436     return DoArithmeticD(Token::SUB, instr);
1437   } else {
1438     ASSERT(instr->representation().IsTagged());
1439     return DoArithmeticT(Token::SUB, instr);
1440   }
1441 }
1442 
1443 
DoAdd(HAdd * instr)1444 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1445   if (instr->representation().IsInteger32()) {
1446     ASSERT(instr->left()->representation().IsInteger32());
1447     ASSERT(instr->right()->representation().IsInteger32());
1448     LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1449     LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1450     LAddI* add = new(zone()) LAddI(left, right);
1451     LInstruction* result = DefineSameAsFirst(add);
1452     if (instr->CheckFlag(HValue::kCanOverflow)) {
1453       result = AssignEnvironment(result);
1454     }
1455     return result;
1456   } else if (instr->representation().IsDouble()) {
1457     return DoArithmeticD(Token::ADD, instr);
1458   } else {
1459     ASSERT(instr->representation().IsTagged());
1460     return DoArithmeticT(Token::ADD, instr);
1461   }
1462 }
1463 
1464 
DoPower(HPower * instr)1465 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1466   ASSERT(instr->representation().IsDouble());
1467   // We call a C function for double power. It can't trigger a GC.
1468   // We need to use fixed result register for the call.
1469   Representation exponent_type = instr->right()->representation();
1470   ASSERT(instr->left()->representation().IsDouble());
1471   LOperand* left = UseFixedDouble(instr->left(), xmm2);
1472   LOperand* right = exponent_type.IsDouble() ?
1473       UseFixedDouble(instr->right(), xmm1) :
1474       UseFixed(instr->right(), eax);
1475   LPower* result = new(zone()) LPower(left, right);
1476   return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
1477                     CAN_DEOPTIMIZE_EAGERLY);
1478 }
1479 
1480 
DoRandom(HRandom * instr)1481 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1482   ASSERT(instr->representation().IsDouble());
1483   ASSERT(instr->global_object()->representation().IsTagged());
1484   LOperand* global_object = UseFixed(instr->global_object(), eax);
1485   LRandom* result = new(zone()) LRandom(global_object);
1486   return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1487 }
1488 
1489 
DoCompareGeneric(HCompareGeneric * instr)1490 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1491   ASSERT(instr->left()->representation().IsTagged());
1492   ASSERT(instr->right()->representation().IsTagged());
1493   LOperand* context = UseFixed(instr->context(), esi);
1494   LOperand* left = UseFixed(instr->left(), edx);
1495   LOperand* right = UseFixed(instr->right(), eax);
1496   LCmpT* result = new(zone()) LCmpT(context, left, right);
1497   return MarkAsCall(DefineFixed(result, eax), instr);
1498 }
1499 
1500 
DoCompareIDAndBranch(HCompareIDAndBranch * instr)1501 LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1502     HCompareIDAndBranch* instr) {
1503   Representation r = instr->GetInputRepresentation();
1504   if (r.IsInteger32()) {
1505     ASSERT(instr->left()->representation().IsInteger32());
1506     ASSERT(instr->right()->representation().IsInteger32());
1507     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1508     LOperand* right = UseOrConstantAtStart(instr->right());
1509     return new(zone()) LCmpIDAndBranch(left, right);
1510   } else {
1511     ASSERT(r.IsDouble());
1512     ASSERT(instr->left()->representation().IsDouble());
1513     ASSERT(instr->right()->representation().IsDouble());
1514     LOperand* left;
1515     LOperand* right;
1516     if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1517       left = UseRegisterOrConstantAtStart(instr->left());
1518       right = UseRegisterOrConstantAtStart(instr->right());
1519     } else {
1520       left = UseRegisterAtStart(instr->left());
1521       right = UseRegisterAtStart(instr->right());
1522     }
1523     return new(zone()) LCmpIDAndBranch(left, right);
1524   }
1525 }
1526 
1527 
DoCompareObjectEqAndBranch(HCompareObjectEqAndBranch * instr)1528 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1529     HCompareObjectEqAndBranch* instr) {
1530   LOperand* left = UseRegisterAtStart(instr->left());
1531   LOperand* right = UseAtStart(instr->right());
1532   return new(zone()) LCmpObjectEqAndBranch(left, right);
1533 }
1534 
1535 
DoCompareConstantEqAndBranch(HCompareConstantEqAndBranch * instr)1536 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1537   HCompareConstantEqAndBranch* instr) {
1538   return new(zone()) LCmpConstantEqAndBranch(
1539       UseRegisterAtStart(instr->value()));
1540 }
1541 
1542 
DoIsNilAndBranch(HIsNilAndBranch * instr)1543 LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
1544   // We only need a temp register for non-strict compare.
1545   LOperand* temp = instr->kind() == kStrictEquality ? NULL : TempRegister();
1546   return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()), temp);
1547 }
1548 
1549 
DoIsObjectAndBranch(HIsObjectAndBranch * instr)1550 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1551   ASSERT(instr->value()->representation().IsTagged());
1552   LOperand* temp = TempRegister();
1553   return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp);
1554 }
1555 
1556 
DoIsStringAndBranch(HIsStringAndBranch * instr)1557 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1558   ASSERT(instr->value()->representation().IsTagged());
1559   LOperand* temp = TempRegister();
1560   return new LIsStringAndBranch(UseRegister(instr->value()), temp);
1561 }
1562 
1563 
DoIsSmiAndBranch(HIsSmiAndBranch * instr)1564 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1565   ASSERT(instr->value()->representation().IsTagged());
1566   return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1567 }
1568 
1569 
DoIsUndetectableAndBranch(HIsUndetectableAndBranch * instr)1570 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1571     HIsUndetectableAndBranch* instr) {
1572   ASSERT(instr  ->value()->representation().IsTagged());
1573   return new(zone()) LIsUndetectableAndBranch(
1574       UseRegisterAtStart(instr->value()), TempRegister());
1575 }
1576 
1577 
DoStringCompareAndBranch(HStringCompareAndBranch * instr)1578 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1579     HStringCompareAndBranch* instr) {
1580   ASSERT(instr->left()->representation().IsTagged());
1581   ASSERT(instr->right()->representation().IsTagged());
1582   LOperand* context = UseFixed(instr->context(), esi);
1583   LOperand* left = UseFixed(instr->left(), edx);
1584   LOperand* right = UseFixed(instr->right(), eax);
1585 
1586   LStringCompareAndBranch* result = new
1587       LStringCompareAndBranch(context, left, right);
1588 
1589   return MarkAsCall(result, instr);
1590 }
1591 
1592 
DoHasInstanceTypeAndBranch(HHasInstanceTypeAndBranch * instr)1593 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1594     HHasInstanceTypeAndBranch* instr) {
1595   ASSERT(instr->value()->representation().IsTagged());
1596   return new(zone()) LHasInstanceTypeAndBranch(
1597       UseRegisterAtStart(instr->value()),
1598       TempRegister());
1599 }
1600 
1601 
DoGetCachedArrayIndex(HGetCachedArrayIndex * instr)1602 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1603     HGetCachedArrayIndex* instr)  {
1604   ASSERT(instr->value()->representation().IsTagged());
1605   LOperand* value = UseRegisterAtStart(instr->value());
1606 
1607   return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
1608 }
1609 
1610 
DoHasCachedArrayIndexAndBranch(HHasCachedArrayIndexAndBranch * instr)1611 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1612     HHasCachedArrayIndexAndBranch* instr) {
1613   ASSERT(instr->value()->representation().IsTagged());
1614   return new(zone()) LHasCachedArrayIndexAndBranch(
1615       UseRegisterAtStart(instr->value()));
1616 }
1617 
1618 
DoClassOfTestAndBranch(HClassOfTestAndBranch * instr)1619 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1620     HClassOfTestAndBranch* instr) {
1621   ASSERT(instr->value()->representation().IsTagged());
1622   return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1623                                            TempRegister(),
1624                                            TempRegister());
1625 }
1626 
1627 
DoJSArrayLength(HJSArrayLength * instr)1628 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1629   LOperand* array = UseRegisterAtStart(instr->value());
1630   return DefineAsRegister(new(zone()) LJSArrayLength(array));
1631 }
1632 
1633 
DoFixedArrayBaseLength(HFixedArrayBaseLength * instr)1634 LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1635     HFixedArrayBaseLength* instr) {
1636   LOperand* array = UseRegisterAtStart(instr->value());
1637   return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
1638 }
1639 
1640 
DoElementsKind(HElementsKind * instr)1641 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1642   LOperand* object = UseRegisterAtStart(instr->value());
1643   return DefineAsRegister(new(zone()) LElementsKind(object));
1644 }
1645 
1646 
DoValueOf(HValueOf * instr)1647 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1648   LOperand* object = UseRegister(instr->value());
1649   LValueOf* result = new(zone()) LValueOf(object, TempRegister());
1650   return DefineSameAsFirst(result);
1651 }
1652 
1653 
DoDateField(HDateField * instr)1654 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1655   LOperand* date = UseFixed(instr->value(), eax);
1656   LDateField* result =
1657       new(zone()) LDateField(date, FixedTemp(ecx), instr->index());
1658   return MarkAsCall(DefineFixed(result, eax), instr);
1659 }
1660 
1661 
DoBoundsCheck(HBoundsCheck * instr)1662 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1663   return AssignEnvironment(new(zone()) LBoundsCheck(
1664       UseRegisterOrConstantAtStart(instr->index()),
1665       UseAtStart(instr->length())));
1666 }
1667 
1668 
DoAbnormalExit(HAbnormalExit * instr)1669 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1670   // The control instruction marking the end of a block that completed
1671   // abruptly (e.g., threw an exception).  There is nothing specific to do.
1672   return NULL;
1673 }
1674 
1675 
DoThrow(HThrow * instr)1676 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1677   LOperand* context = UseFixed(instr->context(), esi);
1678   LOperand* value = UseFixed(instr->value(), eax);
1679   return MarkAsCall(new(zone()) LThrow(context, value), instr);
1680 }
1681 
1682 
DoUseConst(HUseConst * instr)1683 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1684   return NULL;
1685 }
1686 
1687 
DoForceRepresentation(HForceRepresentation * bad)1688 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1689   // All HForceRepresentation instructions should be eliminated in the
1690   // representation change phase of Hydrogen.
1691   UNREACHABLE();
1692   return NULL;
1693 }
1694 
1695 
DoChange(HChange * instr)1696 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1697   Representation from = instr->from();
1698   Representation to = instr->to();
1699   if (from.IsTagged()) {
1700     if (to.IsDouble()) {
1701       LOperand* value = UseRegister(instr->value());
1702       // Temp register only necessary for minus zero check.
1703       LOperand* temp = instr->deoptimize_on_minus_zero()
1704                        ? TempRegister()
1705                        : NULL;
1706       LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp);
1707       return AssignEnvironment(DefineAsRegister(res));
1708     } else {
1709       ASSERT(to.IsInteger32());
1710       LOperand* value = UseRegister(instr->value());
1711       bool needs_check = !instr->value()->type().IsSmi();
1712       if (needs_check) {
1713         bool truncating = instr->CanTruncateToInt32();
1714         LOperand* xmm_temp =
1715             (truncating && CpuFeatures::IsSupported(SSE3))
1716             ? NULL
1717             : FixedTemp(xmm1);
1718         LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp);
1719         return AssignEnvironment(DefineSameAsFirst(res));
1720       } else {
1721         return DefineSameAsFirst(new(zone()) LSmiUntag(value, needs_check));
1722       }
1723     }
1724   } else if (from.IsDouble()) {
1725     if (to.IsTagged()) {
1726       LOperand* value = UseRegister(instr->value());
1727       LOperand* temp = TempRegister();
1728 
1729       // Make sure that temp and result_temp are different registers.
1730       LUnallocated* result_temp = TempRegister();
1731       LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
1732       return AssignPointerMap(Define(result, result_temp));
1733     } else {
1734       ASSERT(to.IsInteger32());
1735       bool truncating = instr->CanTruncateToInt32();
1736       bool needs_temp = truncating && !CpuFeatures::IsSupported(SSE3);
1737       LOperand* value = needs_temp ?
1738           UseTempRegister(instr->value()) : UseRegister(instr->value());
1739       LOperand* temp = needs_temp ? TempRegister() : NULL;
1740       return AssignEnvironment(
1741           DefineAsRegister(new(zone()) LDoubleToI(value, temp)));
1742     }
1743   } else if (from.IsInteger32()) {
1744     if (to.IsTagged()) {
1745       HValue* val = instr->value();
1746       LOperand* value = UseRegister(val);
1747       if (val->HasRange() && val->range()->IsInSmiRange()) {
1748         return DefineSameAsFirst(new(zone()) LSmiTag(value));
1749       } else {
1750         LNumberTagI* result = new(zone()) LNumberTagI(value);
1751         return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1752       }
1753     } else {
1754       ASSERT(to.IsDouble());
1755       return DefineAsRegister(
1756           new(zone()) LInteger32ToDouble(Use(instr->value())));
1757     }
1758   }
1759   UNREACHABLE();
1760   return NULL;
1761 }
1762 
1763 
DoCheckNonSmi(HCheckNonSmi * instr)1764 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1765   LOperand* value = UseAtStart(instr->value());
1766   return AssignEnvironment(new(zone()) LCheckNonSmi(value));
1767 }
1768 
1769 
DoCheckInstanceType(HCheckInstanceType * instr)1770 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1771   LOperand* value = UseRegisterAtStart(instr->value());
1772   LOperand* temp = TempRegister();
1773   LCheckInstanceType* result = new(zone()) LCheckInstanceType(value, temp);
1774   return AssignEnvironment(result);
1775 }
1776 
1777 
DoCheckPrototypeMaps(HCheckPrototypeMaps * instr)1778 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1779   LOperand* temp = TempRegister();
1780   LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp);
1781   return AssignEnvironment(result);
1782 }
1783 
1784 
DoCheckSmi(HCheckSmi * instr)1785 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1786   LOperand* value = UseAtStart(instr->value());
1787   return AssignEnvironment(new(zone()) LCheckSmi(value));
1788 }
1789 
1790 
DoCheckFunction(HCheckFunction * instr)1791 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1792   // If the target is in new space, we'll emit a global cell compare and so
1793   // want the value in a register.  If the target gets promoted before we
1794   // emit code, we will still get the register but will do an immediate
1795   // compare instead of the cell compare.  This is safe.
1796   LOperand* value = Isolate::Current()->heap()->InNewSpace(*instr->target())
1797       ? UseRegisterAtStart(instr->value())
1798       : UseAtStart(instr->value());
1799   return AssignEnvironment(new(zone()) LCheckFunction(value));
1800 }
1801 
1802 
DoCheckMap(HCheckMap * instr)1803 LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1804   LOperand* value = UseRegisterAtStart(instr->value());
1805   LCheckMap* result = new(zone()) LCheckMap(value);
1806   return AssignEnvironment(result);
1807 }
1808 
1809 
DoClampToUint8(HClampToUint8 * instr)1810 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1811   HValue* value = instr->value();
1812   Representation input_rep = value->representation();
1813   if (input_rep.IsDouble()) {
1814     LOperand* reg = UseRegister(value);
1815     return DefineAsRegister(new(zone()) LClampDToUint8(reg));
1816   } else if (input_rep.IsInteger32()) {
1817     LOperand* reg = UseFixed(value, eax);
1818     return DefineFixed(new(zone()) LClampIToUint8(reg), eax);
1819   } else {
1820     ASSERT(input_rep.IsTagged());
1821     LOperand* reg = UseFixed(value, eax);
1822     // Register allocator doesn't (yet) support allocation of double
1823     // temps. Reserve xmm1 explicitly.
1824     LOperand* temp = FixedTemp(xmm1);
1825     LClampTToUint8* result = new(zone()) LClampTToUint8(reg, temp);
1826     return AssignEnvironment(DefineFixed(result, eax));
1827   }
1828 }
1829 
1830 
DoReturn(HReturn * instr)1831 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1832   return new(zone()) LReturn(UseFixed(instr->value(), eax));
1833 }
1834 
1835 
DoConstant(HConstant * instr)1836 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1837   Representation r = instr->representation();
1838   if (r.IsInteger32()) {
1839     return DefineAsRegister(new(zone()) LConstantI);
1840   } else if (r.IsDouble()) {
1841     double value = instr->DoubleValue();
1842     LOperand* temp = (BitCast<uint64_t, double>(value) != 0)
1843         ? TempRegister()
1844         : NULL;
1845     return DefineAsRegister(new(zone()) LConstantD(temp));
1846   } else if (r.IsTagged()) {
1847     return DefineAsRegister(new(zone()) LConstantT);
1848   } else {
1849     UNREACHABLE();
1850     return NULL;
1851   }
1852 }
1853 
1854 
DoLoadGlobalCell(HLoadGlobalCell * instr)1855 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1856   LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
1857   return instr->RequiresHoleCheck()
1858       ? AssignEnvironment(DefineAsRegister(result))
1859       : DefineAsRegister(result);
1860 }
1861 
1862 
DoLoadGlobalGeneric(HLoadGlobalGeneric * instr)1863 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1864   LOperand* context = UseFixed(instr->context(), esi);
1865   LOperand* global_object = UseFixed(instr->global_object(), eax);
1866   LLoadGlobalGeneric* result =
1867       new(zone()) LLoadGlobalGeneric(context, global_object);
1868   return MarkAsCall(DefineFixed(result, eax), instr);
1869 }
1870 
1871 
DoStoreGlobalCell(HStoreGlobalCell * instr)1872 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1873   LStoreGlobalCell* result =
1874       new(zone()) LStoreGlobalCell(UseRegister(instr->value()));
1875   return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1876 }
1877 
1878 
DoStoreGlobalGeneric(HStoreGlobalGeneric * instr)1879 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1880   LOperand* context = UseFixed(instr->context(), esi);
1881   LOperand* global_object = UseFixed(instr->global_object(), edx);
1882   LOperand* value = UseFixed(instr->value(), eax);
1883   LStoreGlobalGeneric* result =
1884       new(zone()) LStoreGlobalGeneric(context, global_object, value);
1885   return MarkAsCall(result, instr);
1886 }
1887 
1888 
DoLoadContextSlot(HLoadContextSlot * instr)1889 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1890   LOperand* context = UseRegisterAtStart(instr->value());
1891   LInstruction* result =
1892       DefineAsRegister(new(zone()) LLoadContextSlot(context));
1893   return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1894 }
1895 
1896 
DoStoreContextSlot(HStoreContextSlot * instr)1897 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1898   LOperand* value;
1899   LOperand* temp;
1900   LOperand* context = UseRegister(instr->context());
1901   if (instr->NeedsWriteBarrier()) {
1902     value = UseTempRegister(instr->value());
1903     temp = TempRegister();
1904   } else {
1905     value = UseRegister(instr->value());
1906     temp = NULL;
1907   }
1908   LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
1909   return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1910 }
1911 
1912 
DoLoadNamedField(HLoadNamedField * instr)1913 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1914   ASSERT(instr->representation().IsTagged());
1915   LOperand* obj = UseRegisterAtStart(instr->object());
1916   return DefineAsRegister(new(zone()) LLoadNamedField(obj));
1917 }
1918 
1919 
DoLoadNamedFieldPolymorphic(HLoadNamedFieldPolymorphic * instr)1920 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1921     HLoadNamedFieldPolymorphic* instr) {
1922   ASSERT(instr->representation().IsTagged());
1923   if (instr->need_generic()) {
1924     LOperand* context = UseFixed(instr->context(), esi);
1925     LOperand* obj = UseFixed(instr->object(), eax);
1926     LLoadNamedFieldPolymorphic* result =
1927         new(zone()) LLoadNamedFieldPolymorphic(context, obj);
1928     return MarkAsCall(DefineFixed(result, eax), instr);
1929   } else {
1930     LOperand* context = UseAny(instr->context());  // Not actually used.
1931     LOperand* obj = UseRegisterAtStart(instr->object());
1932     LLoadNamedFieldPolymorphic* result =
1933         new(zone()) LLoadNamedFieldPolymorphic(context, obj);
1934     return AssignEnvironment(DefineAsRegister(result));
1935   }
1936 }
1937 
1938 
DoLoadNamedGeneric(HLoadNamedGeneric * instr)1939 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1940   LOperand* context = UseFixed(instr->context(), esi);
1941   LOperand* object = UseFixed(instr->object(), eax);
1942   LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
1943   return MarkAsCall(DefineFixed(result, eax), instr);
1944 }
1945 
1946 
DoLoadFunctionPrototype(HLoadFunctionPrototype * instr)1947 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1948     HLoadFunctionPrototype* instr) {
1949   return AssignEnvironment(DefineAsRegister(
1950       new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()),
1951                                          TempRegister())));
1952 }
1953 
1954 
DoLoadElements(HLoadElements * instr)1955 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1956   LOperand* input = UseRegisterAtStart(instr->value());
1957   return DefineAsRegister(new(zone()) LLoadElements(input));
1958 }
1959 
1960 
DoLoadExternalArrayPointer(HLoadExternalArrayPointer * instr)1961 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1962     HLoadExternalArrayPointer* instr) {
1963   LOperand* input = UseRegisterAtStart(instr->value());
1964   return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
1965 }
1966 
1967 
DoLoadKeyedFastElement(HLoadKeyedFastElement * instr)1968 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1969     HLoadKeyedFastElement* instr) {
1970   ASSERT(instr->representation().IsTagged());
1971   ASSERT(instr->key()->representation().IsInteger32());
1972   LOperand* obj = UseRegisterAtStart(instr->object());
1973   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1974   LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
1975   if (instr->RequiresHoleCheck()) AssignEnvironment(result);
1976   return DefineAsRegister(result);
1977 }
1978 
1979 
DoLoadKeyedFastDoubleElement(HLoadKeyedFastDoubleElement * instr)1980 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1981     HLoadKeyedFastDoubleElement* instr) {
1982   ASSERT(instr->representation().IsDouble());
1983   ASSERT(instr->key()->representation().IsInteger32());
1984   LOperand* elements = UseRegisterAtStart(instr->elements());
1985   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1986   LLoadKeyedFastDoubleElement* result =
1987       new(zone()) LLoadKeyedFastDoubleElement(elements, key);
1988   return AssignEnvironment(DefineAsRegister(result));
1989 }
1990 
1991 
DoLoadKeyedSpecializedArrayElement(HLoadKeyedSpecializedArrayElement * instr)1992 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1993     HLoadKeyedSpecializedArrayElement* instr) {
1994   ElementsKind elements_kind = instr->elements_kind();
1995   ASSERT(
1996       (instr->representation().IsInteger32() &&
1997        (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1998        (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
1999       (instr->representation().IsDouble() &&
2000        ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2001        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2002   ASSERT(instr->key()->representation().IsInteger32());
2003   LOperand* external_pointer = UseRegister(instr->external_pointer());
2004   LOperand* key = UseRegisterOrConstant(instr->key());
2005   LLoadKeyedSpecializedArrayElement* result =
2006       new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer,
2007                                             key);
2008   LInstruction* load_instr = DefineAsRegister(result);
2009   // An unsigned int array load might overflow and cause a deopt, make sure it
2010   // has an environment.
2011   return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS)
2012       ? AssignEnvironment(load_instr)
2013       : load_instr;
2014 }
2015 
2016 
DoLoadKeyedGeneric(HLoadKeyedGeneric * instr)2017 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2018   LOperand* context = UseFixed(instr->context(), esi);
2019   LOperand* object = UseFixed(instr->object(), edx);
2020   LOperand* key = UseFixed(instr->key(), eax);
2021 
2022   LLoadKeyedGeneric* result =
2023       new(zone()) LLoadKeyedGeneric(context, object, key);
2024   return MarkAsCall(DefineFixed(result, eax), instr);
2025 }
2026 
2027 
DoStoreKeyedFastElement(HStoreKeyedFastElement * instr)2028 LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
2029     HStoreKeyedFastElement* instr) {
2030   bool needs_write_barrier = instr->NeedsWriteBarrier();
2031   ASSERT(instr->value()->representation().IsTagged());
2032   ASSERT(instr->object()->representation().IsTagged());
2033   ASSERT(instr->key()->representation().IsInteger32());
2034 
2035   LOperand* obj = UseRegister(instr->object());
2036   LOperand* val = needs_write_barrier
2037       ? UseTempRegister(instr->value())
2038       : UseRegisterAtStart(instr->value());
2039   LOperand* key = needs_write_barrier
2040       ? UseTempRegister(instr->key())
2041       : UseRegisterOrConstantAtStart(instr->key());
2042   return new(zone()) LStoreKeyedFastElement(obj, key, val);
2043 }
2044 
2045 
DoStoreKeyedFastDoubleElement(HStoreKeyedFastDoubleElement * instr)2046 LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
2047     HStoreKeyedFastDoubleElement* instr) {
2048   ASSERT(instr->value()->representation().IsDouble());
2049   ASSERT(instr->elements()->representation().IsTagged());
2050   ASSERT(instr->key()->representation().IsInteger32());
2051 
2052   LOperand* elements = UseRegisterAtStart(instr->elements());
2053   LOperand* val = UseTempRegister(instr->value());
2054   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2055 
2056   return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
2057 }
2058 
2059 
DoStoreKeyedSpecializedArrayElement(HStoreKeyedSpecializedArrayElement * instr)2060 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
2061     HStoreKeyedSpecializedArrayElement* instr) {
2062   ElementsKind elements_kind = instr->elements_kind();
2063     ASSERT(
2064       (instr->value()->representation().IsInteger32() &&
2065        (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2066        (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2067       (instr->value()->representation().IsDouble() &&
2068        ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2069        (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2070   ASSERT(instr->external_pointer()->representation().IsExternal());
2071   ASSERT(instr->key()->representation().IsInteger32());
2072 
2073   LOperand* external_pointer = UseRegister(instr->external_pointer());
2074   LOperand* key = UseRegisterOrConstant(instr->key());
2075   LOperand* val = NULL;
2076   if (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
2077       elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
2078       elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
2079     // We need a byte register in this case for the value.
2080     val = UseFixed(instr->value(), eax);
2081   } else {
2082     val = UseRegister(instr->value());
2083   }
2084 
2085   return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
2086                                                         key,
2087                                                         val);
2088 }
2089 
2090 
DoStoreKeyedGeneric(HStoreKeyedGeneric * instr)2091 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2092   LOperand* context = UseFixed(instr->context(), esi);
2093   LOperand* object = UseFixed(instr->object(), edx);
2094   LOperand* key = UseFixed(instr->key(), ecx);
2095   LOperand* value = UseFixed(instr->value(), eax);
2096 
2097   ASSERT(instr->object()->representation().IsTagged());
2098   ASSERT(instr->key()->representation().IsTagged());
2099   ASSERT(instr->value()->representation().IsTagged());
2100 
2101   LStoreKeyedGeneric* result =
2102       new(zone()) LStoreKeyedGeneric(context, object, key, value);
2103   return MarkAsCall(result, instr);
2104 }
2105 
2106 
DoTransitionElementsKind(HTransitionElementsKind * instr)2107 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2108     HTransitionElementsKind* instr) {
2109   if (instr->original_map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2110       instr->transitioned_map()->elements_kind() == FAST_ELEMENTS) {
2111     LOperand* object = UseRegister(instr->object());
2112     LOperand* new_map_reg = TempRegister();
2113     LOperand* temp_reg = TempRegister();
2114     LTransitionElementsKind* result =
2115         new(zone()) LTransitionElementsKind(object, new_map_reg, temp_reg);
2116     return DefineSameAsFirst(result);
2117   } else {
2118     LOperand* object = UseFixed(instr->object(), eax);
2119     LOperand* fixed_object_reg = FixedTemp(edx);
2120     LOperand* new_map_reg = FixedTemp(ebx);
2121     LTransitionElementsKind* result =
2122         new(zone()) LTransitionElementsKind(object,
2123                                             new_map_reg,
2124                                             fixed_object_reg);
2125     return MarkAsCall(DefineFixed(result, eax), instr);
2126   }
2127 }
2128 
2129 
DoStoreNamedField(HStoreNamedField * instr)2130 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2131   bool needs_write_barrier = instr->NeedsWriteBarrier();
2132 
2133   LOperand* obj;
2134   if (needs_write_barrier) {
2135     obj = instr->is_in_object()
2136         ? UseRegister(instr->object())
2137         : UseTempRegister(instr->object());
2138   } else {
2139     obj = UseRegisterAtStart(instr->object());
2140   }
2141 
2142   LOperand* val = needs_write_barrier
2143       ? UseTempRegister(instr->value())
2144       : UseRegister(instr->value());
2145 
2146   // We only need a scratch register if we have a write barrier or we
2147   // have a store into the properties array (not in-object-property).
2148   LOperand* temp = (!instr->is_in_object() || needs_write_barrier)
2149       ? TempRegister()
2150       : NULL;
2151 
2152   return new(zone()) LStoreNamedField(obj, val, temp);
2153 }
2154 
2155 
DoStoreNamedGeneric(HStoreNamedGeneric * instr)2156 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2157   LOperand* context = UseFixed(instr->context(), esi);
2158   LOperand* object = UseFixed(instr->object(), edx);
2159   LOperand* value = UseFixed(instr->value(), eax);
2160 
2161   LStoreNamedGeneric* result =
2162       new(zone()) LStoreNamedGeneric(context, object, value);
2163   return MarkAsCall(result, instr);
2164 }
2165 
2166 
DoStringAdd(HStringAdd * instr)2167 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2168   LOperand* context = UseFixed(instr->context(), esi);
2169   LOperand* left = UseOrConstantAtStart(instr->left());
2170   LOperand* right = UseOrConstantAtStart(instr->right());
2171   LStringAdd* string_add = new(zone()) LStringAdd(context, left, right);
2172   return MarkAsCall(DefineFixed(string_add, eax), instr);
2173 }
2174 
2175 
DoStringCharCodeAt(HStringCharCodeAt * instr)2176 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2177   LOperand* string = UseTempRegister(instr->string());
2178   LOperand* index = UseTempRegister(instr->index());
2179   LOperand* context = UseAny(instr->context());
2180   LStringCharCodeAt* result =
2181       new(zone()) LStringCharCodeAt(context, string, index);
2182   return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2183 }
2184 
2185 
DoStringCharFromCode(HStringCharFromCode * instr)2186 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2187   LOperand* char_code = UseRegister(instr->value());
2188   LOperand* context = UseAny(instr->context());
2189   LStringCharFromCode* result =
2190       new(zone()) LStringCharFromCode(context, char_code);
2191   return AssignPointerMap(DefineAsRegister(result));
2192 }
2193 
2194 
DoStringLength(HStringLength * instr)2195 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2196   LOperand* string = UseRegisterAtStart(instr->value());
2197   return DefineAsRegister(new(zone()) LStringLength(string));
2198 }
2199 
2200 
DoAllocateObject(HAllocateObject * instr)2201 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
2202   LOperand* context = UseFixed(instr->context(), esi);
2203   LOperand* temp = TempRegister();
2204   LAllocateObject* result = new(zone()) LAllocateObject(context, temp);
2205   return AssignPointerMap(DefineAsRegister(result));
2206 }
2207 
2208 
DoFastLiteral(HFastLiteral * instr)2209 LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
2210   LOperand* context = UseFixed(instr->context(), esi);
2211   return MarkAsCall(
2212       DefineFixed(new(zone()) LFastLiteral(context), eax), instr);
2213 }
2214 
2215 
DoArrayLiteral(HArrayLiteral * instr)2216 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2217   LOperand* context = UseFixed(instr->context(), esi);
2218   return MarkAsCall(
2219       DefineFixed(new(zone()) LArrayLiteral(context), eax), instr);
2220 }
2221 
2222 
DoObjectLiteral(HObjectLiteral * instr)2223 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2224   LOperand* context = UseFixed(instr->context(), esi);
2225   return MarkAsCall(
2226       DefineFixed(new(zone()) LObjectLiteral(context), eax), instr);
2227 }
2228 
2229 
DoRegExpLiteral(HRegExpLiteral * instr)2230 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2231   LOperand* context = UseFixed(instr->context(), esi);
2232   return MarkAsCall(
2233       DefineFixed(new(zone()) LRegExpLiteral(context), eax), instr);
2234 }
2235 
2236 
DoFunctionLiteral(HFunctionLiteral * instr)2237 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2238   LOperand* context = UseFixed(instr->context(), esi);
2239   return MarkAsCall(
2240       DefineFixed(new(zone()) LFunctionLiteral(context), eax), instr);
2241 }
2242 
2243 
DoDeleteProperty(HDeleteProperty * instr)2244 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
2245   LOperand* context = UseFixed(instr->context(), esi);
2246   LOperand* object = UseAtStart(instr->object());
2247   LOperand* key = UseOrConstantAtStart(instr->key());
2248   LDeleteProperty* result = new(zone()) LDeleteProperty(context, object, key);
2249   return MarkAsCall(DefineFixed(result, eax), instr);
2250 }
2251 
2252 
DoOsrEntry(HOsrEntry * instr)2253 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2254   allocator_->MarkAsOsrEntry();
2255   current_block_->last_environment()->set_ast_id(instr->ast_id());
2256   return AssignEnvironment(new(zone()) LOsrEntry);
2257 }
2258 
2259 
DoParameter(HParameter * instr)2260 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2261   int spill_index = chunk()->GetParameterStackSlot(instr->index());
2262   return DefineAsSpilled(new(zone()) LParameter, spill_index);
2263 }
2264 
2265 
DoUnknownOSRValue(HUnknownOSRValue * instr)2266 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2267   int spill_index = chunk()->GetNextSpillIndex(false);  // Not double-width.
2268   if (spill_index > LUnallocated::kMaxFixedIndex) {
2269     Abort("Too many spill slots needed for OSR");
2270     spill_index = 0;
2271   }
2272   return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
2273 }
2274 
2275 
DoCallStub(HCallStub * instr)2276 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2277   LOperand* context = UseFixed(instr->context(), esi);
2278   argument_count_ -= instr->argument_count();
2279   LCallStub* result = new(zone()) LCallStub(context);
2280   return MarkAsCall(DefineFixed(result, eax), instr);
2281 }
2282 
2283 
DoArgumentsObject(HArgumentsObject * instr)2284 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2285   // There are no real uses of the arguments object.
2286   // arguments.length and element access are supported directly on
2287   // stack arguments, and any real arguments object use causes a bailout.
2288   // So this value is never used.
2289   return NULL;
2290 }
2291 
2292 
DoAccessArgumentsAt(HAccessArgumentsAt * instr)2293 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2294   LOperand* arguments = UseRegister(instr->arguments());
2295   LOperand* length = UseTempRegister(instr->length());
2296   LOperand* index = Use(instr->index());
2297   LAccessArgumentsAt* result =
2298       new(zone()) LAccessArgumentsAt(arguments, length, index);
2299   return AssignEnvironment(DefineAsRegister(result));
2300 }
2301 
2302 
DoToFastProperties(HToFastProperties * instr)2303 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2304   LOperand* object = UseFixed(instr->value(), eax);
2305   LToFastProperties* result = new(zone()) LToFastProperties(object);
2306   return MarkAsCall(DefineFixed(result, eax), instr);
2307 }
2308 
2309 
DoTypeof(HTypeof * instr)2310 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2311   LOperand* context = UseFixed(instr->context(), esi);
2312   LOperand* value = UseAtStart(instr->value());
2313   LTypeof* result = new(zone()) LTypeof(context, value);
2314   return MarkAsCall(DefineFixed(result, eax), instr);
2315 }
2316 
2317 
DoTypeofIsAndBranch(HTypeofIsAndBranch * instr)2318 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2319   return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2320 }
2321 
2322 
DoIsConstructCallAndBranch(HIsConstructCallAndBranch * instr)2323 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2324     HIsConstructCallAndBranch* instr) {
2325   return new(zone()) LIsConstructCallAndBranch(TempRegister());
2326 }
2327 
2328 
DoSimulate(HSimulate * instr)2329 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2330   HEnvironment* env = current_block_->last_environment();
2331   ASSERT(env != NULL);
2332 
2333   env->set_ast_id(instr->ast_id());
2334 
2335   env->Drop(instr->pop_count());
2336   for (int i = 0; i < instr->values()->length(); ++i) {
2337     HValue* value = instr->values()->at(i);
2338     if (instr->HasAssignedIndexAt(i)) {
2339       env->Bind(instr->GetAssignedIndexAt(i), value);
2340     } else {
2341       env->Push(value);
2342     }
2343   }
2344 
2345   // If there is an instruction pending deoptimization environment create a
2346   // lazy bailout instruction to capture the environment.
2347   if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) {
2348     ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
2349     LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
2350     LInstruction* result = AssignEnvironment(lazy_bailout);
2351     instruction_pending_deoptimization_environment_->
2352         set_deoptimization_environment(result->environment());
2353     ClearInstructionPendingDeoptimizationEnvironment();
2354     return result;
2355   }
2356 
2357   return NULL;
2358 }
2359 
2360 
DoStackCheck(HStackCheck * instr)2361 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2362   if (instr->is_function_entry()) {
2363     LOperand* context = UseFixed(instr->context(), esi);
2364     return MarkAsCall(new(zone()) LStackCheck(context), instr);
2365   } else {
2366     ASSERT(instr->is_backwards_branch());
2367     LOperand* context = UseAny(instr->context());
2368     return AssignEnvironment(
2369         AssignPointerMap(new(zone()) LStackCheck(context)));
2370   }
2371 }
2372 
2373 
DoEnterInlined(HEnterInlined * instr)2374 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2375   HEnvironment* outer = current_block_->last_environment();
2376   HConstant* undefined = graph()->GetConstantUndefined();
2377   HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2378                                                instr->arguments_count(),
2379                                                instr->function(),
2380                                                undefined,
2381                                                instr->call_kind(),
2382                                                instr->is_construct());
2383   if (instr->arguments() != NULL) {
2384     inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
2385   }
2386   current_block_->UpdateEnvironment(inner);
2387   chunk_->AddInlinedClosure(instr->closure());
2388   return NULL;
2389 }
2390 
2391 
DoLeaveInlined(HLeaveInlined * instr)2392 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2393   HEnvironment* outer = current_block_->last_environment()->
2394       DiscardInlined(false);
2395   current_block_->UpdateEnvironment(outer);
2396   return NULL;
2397 }
2398 
2399 
DoIn(HIn * instr)2400 LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2401   LOperand* context = UseFixed(instr->context(), esi);
2402   LOperand* key = UseOrConstantAtStart(instr->key());
2403   LOperand* object = UseOrConstantAtStart(instr->object());
2404   LIn* result = new(zone()) LIn(context, key, object);
2405   return MarkAsCall(DefineFixed(result, eax), instr);
2406 }
2407 
2408 
DoForInPrepareMap(HForInPrepareMap * instr)2409 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2410   LOperand* context = UseFixed(instr->context(), esi);
2411   LOperand* object = UseFixed(instr->enumerable(), eax);
2412   LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
2413   return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
2414 }
2415 
2416 
DoForInCacheArray(HForInCacheArray * instr)2417 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2418   LOperand* map = UseRegister(instr->map());
2419   return AssignEnvironment(DefineAsRegister(
2420       new(zone()) LForInCacheArray(map)));
2421 }
2422 
2423 
DoCheckMapValue(HCheckMapValue * instr)2424 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2425   LOperand* value = UseRegisterAtStart(instr->value());
2426   LOperand* map = UseRegisterAtStart(instr->map());
2427   return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
2428 }
2429 
2430 
DoLoadFieldByIndex(HLoadFieldByIndex * instr)2431 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2432   LOperand* object = UseRegister(instr->object());
2433   LOperand* index = UseTempRegister(instr->index());
2434   return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index));
2435 }
2436 
2437 
2438 } }  // namespace v8::internal
2439 
2440 #endif  // V8_TARGET_ARCH_IA32
2441