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