Home | History | Annotate | Download | only in arm
      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 #include "arm/lithium-codegen-arm.h"
     31 #include "arm/lithium-gap-resolver-arm.h"
     32 #include "code-stubs.h"
     33 #include "stub-cache.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 
     39 class SafepointGenerator : public CallWrapper {
     40  public:
     41   SafepointGenerator(LCodeGen* codegen,
     42                      LPointerMap* pointers,
     43                      Safepoint::DeoptMode mode)
     44       : codegen_(codegen),
     45         pointers_(pointers),
     46         deopt_mode_(mode) { }
     47   virtual ~SafepointGenerator() { }
     48 
     49   virtual void BeforeCall(int call_size) const { }
     50 
     51   virtual void AfterCall() const {
     52     codegen_->RecordSafepoint(pointers_, deopt_mode_);
     53   }
     54 
     55  private:
     56   LCodeGen* codegen_;
     57   LPointerMap* pointers_;
     58   Safepoint::DeoptMode deopt_mode_;
     59 };
     60 
     61 
     62 #define __ masm()->
     63 
     64 bool LCodeGen::GenerateCode() {
     65   HPhase phase("Z_Code generation", chunk());
     66   ASSERT(is_unused());
     67   status_ = GENERATING;
     68   CpuFeatures::Scope scope1(VFP3);
     69   CpuFeatures::Scope scope2(ARMv7);
     70 
     71   CodeStub::GenerateFPStubs();
     72 
     73   // Open a frame scope to indicate that there is a frame on the stack.  The
     74   // NONE indicates that the scope shouldn't actually generate code to set up
     75   // the frame (that is done in GeneratePrologue).
     76   FrameScope frame_scope(masm_, StackFrame::NONE);
     77 
     78   return GeneratePrologue() &&
     79       GenerateBody() &&
     80       GenerateDeferredCode() &&
     81       GenerateDeoptJumpTable() &&
     82       GenerateSafepointTable();
     83 }
     84 
     85 
     86 void LCodeGen::FinishCode(Handle<Code> code) {
     87   ASSERT(is_done());
     88   code->set_stack_slots(GetStackSlotCount());
     89   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
     90   PopulateDeoptimizationData(code);
     91 }
     92 
     93 
     94 void LCodeGen::Abort(const char* format, ...) {
     95   if (FLAG_trace_bailout) {
     96     SmartArrayPointer<char> name(
     97         info()->shared_info()->DebugName()->ToCString());
     98     PrintF("Aborting LCodeGen in @\"%s\": ", *name);
     99     va_list arguments;
    100     va_start(arguments, format);
    101     OS::VPrint(format, arguments);
    102     va_end(arguments);
    103     PrintF("\n");
    104   }
    105   status_ = ABORTED;
    106 }
    107 
    108 
    109 void LCodeGen::Comment(const char* format, ...) {
    110   if (!FLAG_code_comments) return;
    111   char buffer[4 * KB];
    112   StringBuilder builder(buffer, ARRAY_SIZE(buffer));
    113   va_list arguments;
    114   va_start(arguments, format);
    115   builder.AddFormattedList(format, arguments);
    116   va_end(arguments);
    117 
    118   // Copy the string before recording it in the assembler to avoid
    119   // issues when the stack allocated buffer goes out of scope.
    120   size_t length = builder.position();
    121   Vector<char> copy = Vector<char>::New(length + 1);
    122   memcpy(copy.start(), builder.Finalize(), copy.length());
    123   masm()->RecordComment(copy.start());
    124 }
    125 
    126 
    127 bool LCodeGen::GeneratePrologue() {
    128   ASSERT(is_generating());
    129 
    130 #ifdef DEBUG
    131   if (strlen(FLAG_stop_at) > 0 &&
    132       info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
    133     __ stop("stop_at");
    134   }
    135 #endif
    136 
    137   // r1: Callee's JS function.
    138   // cp: Callee's context.
    139   // fp: Caller's frame pointer.
    140   // lr: Caller's pc.
    141 
    142   // Strict mode functions and builtins need to replace the receiver
    143   // with undefined when called as functions (without an explicit
    144   // receiver object). r5 is zero for method calls and non-zero for
    145   // function calls.
    146   if (!info_->is_classic_mode() || info_->is_native()) {
    147     Label ok;
    148     __ cmp(r5, Operand(0));
    149     __ b(eq, &ok);
    150     int receiver_offset = scope()->num_parameters() * kPointerSize;
    151     __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
    152     __ str(r2, MemOperand(sp, receiver_offset));
    153     __ bind(&ok);
    154   }
    155 
    156   __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
    157   __ add(fp, sp, Operand(2 * kPointerSize));  // Adjust FP to point to saved FP.
    158 
    159   // Reserve space for the stack slots needed by the code.
    160   int slots = GetStackSlotCount();
    161   if (slots > 0) {
    162     if (FLAG_debug_code) {
    163       __ mov(r0, Operand(slots));
    164       __ mov(r2, Operand(kSlotsZapValue));
    165       Label loop;
    166       __ bind(&loop);
    167       __ push(r2);
    168       __ sub(r0, r0, Operand(1), SetCC);
    169       __ b(ne, &loop);
    170     } else {
    171       __ sub(sp,  sp, Operand(slots * kPointerSize));
    172     }
    173   }
    174 
    175   // Possibly allocate a local context.
    176   int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
    177   if (heap_slots > 0) {
    178     Comment(";;; Allocate local context");
    179     // Argument to NewContext is the function, which is in r1.
    180     __ push(r1);
    181     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
    182       FastNewContextStub stub(heap_slots);
    183       __ CallStub(&stub);
    184     } else {
    185       __ CallRuntime(Runtime::kNewFunctionContext, 1);
    186     }
    187     RecordSafepoint(Safepoint::kNoLazyDeopt);
    188     // Context is returned in both r0 and cp.  It replaces the context
    189     // passed to us.  It's saved in the stack and kept live in cp.
    190     __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
    191     // Copy any necessary parameters into the context.
    192     int num_parameters = scope()->num_parameters();
    193     for (int i = 0; i < num_parameters; i++) {
    194       Variable* var = scope()->parameter(i);
    195       if (var->IsContextSlot()) {
    196         int parameter_offset = StandardFrameConstants::kCallerSPOffset +
    197             (num_parameters - 1 - i) * kPointerSize;
    198         // Load parameter from stack.
    199         __ ldr(r0, MemOperand(fp, parameter_offset));
    200         // Store it in the context.
    201         MemOperand target = ContextOperand(cp, var->index());
    202         __ str(r0, target);
    203         // Update the write barrier. This clobbers r3 and r0.
    204         __ RecordWriteContextSlot(
    205             cp, target.offset(), r0, r3, kLRHasBeenSaved, kSaveFPRegs);
    206       }
    207     }
    208     Comment(";;; End allocate local context");
    209   }
    210 
    211   // Trace the call.
    212   if (FLAG_trace) {
    213     __ CallRuntime(Runtime::kTraceEnter, 0);
    214   }
    215   return !is_aborted();
    216 }
    217 
    218 
    219 bool LCodeGen::GenerateBody() {
    220   ASSERT(is_generating());
    221   bool emit_instructions = true;
    222   for (current_instruction_ = 0;
    223        !is_aborted() && current_instruction_ < instructions_->length();
    224        current_instruction_++) {
    225     LInstruction* instr = instructions_->at(current_instruction_);
    226     if (instr->IsLabel()) {
    227       LLabel* label = LLabel::cast(instr);
    228       emit_instructions = !label->HasReplacement();
    229     }
    230 
    231     if (emit_instructions) {
    232       Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic());
    233       instr->CompileToNative(this);
    234     }
    235   }
    236   EnsureSpaceForLazyDeopt();
    237   return !is_aborted();
    238 }
    239 
    240 
    241 bool LCodeGen::GenerateDeferredCode() {
    242   ASSERT(is_generating());
    243   if (deferred_.length() > 0) {
    244     for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
    245       LDeferredCode* code = deferred_[i];
    246       __ bind(code->entry());
    247       Comment(";;; Deferred code @%d: %s.",
    248               code->instruction_index(),
    249               code->instr()->Mnemonic());
    250       code->Generate();
    251       __ jmp(code->exit());
    252     }
    253   }
    254 
    255   // Force constant pool emission at the end of the deferred code to make
    256   // sure that no constant pools are emitted after.
    257   masm()->CheckConstPool(true, false);
    258 
    259   return !is_aborted();
    260 }
    261 
    262 
    263 bool LCodeGen::GenerateDeoptJumpTable() {
    264   // Check that the jump table is accessible from everywhere in the function
    265   // code, i.e. that offsets to the table can be encoded in the 24bit signed
    266   // immediate of a branch instruction.
    267   // To simplify we consider the code size from the first instruction to the
    268   // end of the jump table. We also don't consider the pc load delta.
    269   // Each entry in the jump table generates one instruction and inlines one
    270   // 32bit data after it.
    271   if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) +
    272       deopt_jump_table_.length() * 2)) {
    273     Abort("Generated code is too large");
    274   }
    275 
    276   // Block the constant pool emission during the jump table emission.
    277   __ BlockConstPoolFor(deopt_jump_table_.length());
    278   __ RecordComment("[ Deoptimisation jump table");
    279   Label table_start;
    280   __ bind(&table_start);
    281   for (int i = 0; i < deopt_jump_table_.length(); i++) {
    282     __ bind(&deopt_jump_table_[i].label);
    283     __ ldr(pc, MemOperand(pc, Assembler::kInstrSize - Assembler::kPcLoadDelta));
    284     __ dd(reinterpret_cast<uint32_t>(deopt_jump_table_[i].address));
    285   }
    286   ASSERT(masm()->InstructionsGeneratedSince(&table_start) ==
    287       deopt_jump_table_.length() * 2);
    288   __ RecordComment("]");
    289 
    290   // The deoptimization jump table is the last part of the instruction
    291   // sequence. Mark the generated code as done unless we bailed out.
    292   if (!is_aborted()) status_ = DONE;
    293   return !is_aborted();
    294 }
    295 
    296 
    297 bool LCodeGen::GenerateSafepointTable() {
    298   ASSERT(is_done());
    299   safepoints_.Emit(masm(), GetStackSlotCount());
    300   return !is_aborted();
    301 }
    302 
    303 
    304 Register LCodeGen::ToRegister(int index) const {
    305   return Register::FromAllocationIndex(index);
    306 }
    307 
    308 
    309 DoubleRegister LCodeGen::ToDoubleRegister(int index) const {
    310   return DoubleRegister::FromAllocationIndex(index);
    311 }
    312 
    313 
    314 Register LCodeGen::ToRegister(LOperand* op) const {
    315   ASSERT(op->IsRegister());
    316   return ToRegister(op->index());
    317 }
    318 
    319 
    320 Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
    321   if (op->IsRegister()) {
    322     return ToRegister(op->index());
    323   } else if (op->IsConstantOperand()) {
    324     LConstantOperand* const_op = LConstantOperand::cast(op);
    325     Handle<Object> literal = chunk_->LookupLiteral(const_op);
    326     Representation r = chunk_->LookupLiteralRepresentation(const_op);
    327     if (r.IsInteger32()) {
    328       ASSERT(literal->IsNumber());
    329       __ mov(scratch, Operand(static_cast<int32_t>(literal->Number())));
    330     } else if (r.IsDouble()) {
    331       Abort("EmitLoadRegister: Unsupported double immediate.");
    332     } else {
    333       ASSERT(r.IsTagged());
    334       if (literal->IsSmi()) {
    335         __ mov(scratch, Operand(literal));
    336       } else {
    337        __ LoadHeapObject(scratch, Handle<HeapObject>::cast(literal));
    338       }
    339     }
    340     return scratch;
    341   } else if (op->IsStackSlot() || op->IsArgument()) {
    342     __ ldr(scratch, ToMemOperand(op));
    343     return scratch;
    344   }
    345   UNREACHABLE();
    346   return scratch;
    347 }
    348 
    349 
    350 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
    351   ASSERT(op->IsDoubleRegister());
    352   return ToDoubleRegister(op->index());
    353 }
    354 
    355 
    356 DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
    357                                                 SwVfpRegister flt_scratch,
    358                                                 DoubleRegister dbl_scratch) {
    359   if (op->IsDoubleRegister()) {
    360     return ToDoubleRegister(op->index());
    361   } else if (op->IsConstantOperand()) {
    362     LConstantOperand* const_op = LConstantOperand::cast(op);
    363     Handle<Object> literal = chunk_->LookupLiteral(const_op);
    364     Representation r = chunk_->LookupLiteralRepresentation(const_op);
    365     if (r.IsInteger32()) {
    366       ASSERT(literal->IsNumber());
    367       __ mov(ip, Operand(static_cast<int32_t>(literal->Number())));
    368       __ vmov(flt_scratch, ip);
    369       __ vcvt_f64_s32(dbl_scratch, flt_scratch);
    370       return dbl_scratch;
    371     } else if (r.IsDouble()) {
    372       Abort("unsupported double immediate");
    373     } else if (r.IsTagged()) {
    374       Abort("unsupported tagged immediate");
    375     }
    376   } else if (op->IsStackSlot() || op->IsArgument()) {
    377     // TODO(regis): Why is vldr not taking a MemOperand?
    378     // __ vldr(dbl_scratch, ToMemOperand(op));
    379     MemOperand mem_op = ToMemOperand(op);
    380     __ vldr(dbl_scratch, mem_op.rn(), mem_op.offset());
    381     return dbl_scratch;
    382   }
    383   UNREACHABLE();
    384   return dbl_scratch;
    385 }
    386 
    387 
    388 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
    389   Handle<Object> literal = chunk_->LookupLiteral(op);
    390   ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
    391   return literal;
    392 }
    393 
    394 
    395 bool LCodeGen::IsInteger32(LConstantOperand* op) const {
    396   return chunk_->LookupLiteralRepresentation(op).IsInteger32();
    397 }
    398 
    399 
    400 int LCodeGen::ToInteger32(LConstantOperand* op) const {
    401   Handle<Object> value = chunk_->LookupLiteral(op);
    402   ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
    403   ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
    404       value->Number());
    405   return static_cast<int32_t>(value->Number());
    406 }
    407 
    408 
    409 double LCodeGen::ToDouble(LConstantOperand* op) const {
    410   Handle<Object> value = chunk_->LookupLiteral(op);
    411   return value->Number();
    412 }
    413 
    414 
    415 Operand LCodeGen::ToOperand(LOperand* op) {
    416   if (op->IsConstantOperand()) {
    417     LConstantOperand* const_op = LConstantOperand::cast(op);
    418     Handle<Object> literal = chunk_->LookupLiteral(const_op);
    419     Representation r = chunk_->LookupLiteralRepresentation(const_op);
    420     if (r.IsInteger32()) {
    421       ASSERT(literal->IsNumber());
    422       return Operand(static_cast<int32_t>(literal->Number()));
    423     } else if (r.IsDouble()) {
    424       Abort("ToOperand Unsupported double immediate.");
    425     }
    426     ASSERT(r.IsTagged());
    427     return Operand(literal);
    428   } else if (op->IsRegister()) {
    429     return Operand(ToRegister(op));
    430   } else if (op->IsDoubleRegister()) {
    431     Abort("ToOperand IsDoubleRegister unimplemented");
    432     return Operand(0);
    433   }
    434   // Stack slots not implemented, use ToMemOperand instead.
    435   UNREACHABLE();
    436   return Operand(0);
    437 }
    438 
    439 
    440 MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
    441   ASSERT(!op->IsRegister());
    442   ASSERT(!op->IsDoubleRegister());
    443   ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
    444   int index = op->index();
    445   if (index >= 0) {
    446     // Local or spill slot. Skip the frame pointer, function, and
    447     // context in the fixed part of the frame.
    448     return MemOperand(fp, -(index + 3) * kPointerSize);
    449   } else {
    450     // Incoming parameter. Skip the return address.
    451     return MemOperand(fp, -(index - 1) * kPointerSize);
    452   }
    453 }
    454 
    455 
    456 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
    457   ASSERT(op->IsDoubleStackSlot());
    458   int index = op->index();
    459   if (index >= 0) {
    460     // Local or spill slot. Skip the frame pointer, function, context,
    461     // and the first word of the double in the fixed part of the frame.
    462     return MemOperand(fp, -(index + 3) * kPointerSize + kPointerSize);
    463   } else {
    464     // Incoming parameter. Skip the return address and the first word of
    465     // the double.
    466     return MemOperand(fp, -(index - 1) * kPointerSize + kPointerSize);
    467   }
    468 }
    469 
    470 
    471 void LCodeGen::WriteTranslation(LEnvironment* environment,
    472                                 Translation* translation) {
    473   if (environment == NULL) return;
    474 
    475   // The translation includes one command per value in the environment.
    476   int translation_size = environment->values()->length();
    477   // The output frame height does not include the parameters.
    478   int height = translation_size - environment->parameter_count();
    479 
    480   WriteTranslation(environment->outer(), translation);
    481   int closure_id = DefineDeoptimizationLiteral(environment->closure());
    482   switch (environment->frame_type()) {
    483     case JS_FUNCTION:
    484       translation->BeginJSFrame(environment->ast_id(), closure_id, height);
    485       break;
    486     case JS_CONSTRUCT:
    487       translation->BeginConstructStubFrame(closure_id, translation_size);
    488       break;
    489     case ARGUMENTS_ADAPTOR:
    490       translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
    491       break;
    492     default:
    493       UNREACHABLE();
    494   }
    495   for (int i = 0; i < translation_size; ++i) {
    496     LOperand* value = environment->values()->at(i);
    497     // spilled_registers_ and spilled_double_registers_ are either
    498     // both NULL or both set.
    499     if (environment->spilled_registers() != NULL && value != NULL) {
    500       if (value->IsRegister() &&
    501           environment->spilled_registers()[value->index()] != NULL) {
    502         translation->MarkDuplicate();
    503         AddToTranslation(translation,
    504                          environment->spilled_registers()[value->index()],
    505                          environment->HasTaggedValueAt(i));
    506       } else if (
    507           value->IsDoubleRegister() &&
    508           environment->spilled_double_registers()[value->index()] != NULL) {
    509         translation->MarkDuplicate();
    510         AddToTranslation(
    511             translation,
    512             environment->spilled_double_registers()[value->index()],
    513             false);
    514       }
    515     }
    516 
    517     AddToTranslation(translation, value, environment->HasTaggedValueAt(i));
    518   }
    519 }
    520 
    521 
    522 void LCodeGen::AddToTranslation(Translation* translation,
    523                                 LOperand* op,
    524                                 bool is_tagged) {
    525   if (op == NULL) {
    526     // TODO(twuerthinger): Introduce marker operands to indicate that this value
    527     // is not present and must be reconstructed from the deoptimizer. Currently
    528     // this is only used for the arguments object.
    529     translation->StoreArgumentsObject();
    530   } else if (op->IsStackSlot()) {
    531     if (is_tagged) {
    532       translation->StoreStackSlot(op->index());
    533     } else {
    534       translation->StoreInt32StackSlot(op->index());
    535     }
    536   } else if (op->IsDoubleStackSlot()) {
    537     translation->StoreDoubleStackSlot(op->index());
    538   } else if (op->IsArgument()) {
    539     ASSERT(is_tagged);
    540     int src_index = GetStackSlotCount() + op->index();
    541     translation->StoreStackSlot(src_index);
    542   } else if (op->IsRegister()) {
    543     Register reg = ToRegister(op);
    544     if (is_tagged) {
    545       translation->StoreRegister(reg);
    546     } else {
    547       translation->StoreInt32Register(reg);
    548     }
    549   } else if (op->IsDoubleRegister()) {
    550     DoubleRegister reg = ToDoubleRegister(op);
    551     translation->StoreDoubleRegister(reg);
    552   } else if (op->IsConstantOperand()) {
    553     Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op));
    554     int src_index = DefineDeoptimizationLiteral(literal);
    555     translation->StoreLiteral(src_index);
    556   } else {
    557     UNREACHABLE();
    558   }
    559 }
    560 
    561 
    562 void LCodeGen::CallCode(Handle<Code> code,
    563                         RelocInfo::Mode mode,
    564                         LInstruction* instr) {
    565   CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
    566 }
    567 
    568 
    569 void LCodeGen::CallCodeGeneric(Handle<Code> code,
    570                                RelocInfo::Mode mode,
    571                                LInstruction* instr,
    572                                SafepointMode safepoint_mode) {
    573   ASSERT(instr != NULL);
    574   LPointerMap* pointers = instr->pointer_map();
    575   RecordPosition(pointers->position());
    576   __ Call(code, mode);
    577   RecordSafepointWithLazyDeopt(instr, safepoint_mode);
    578 
    579   // Signal that we don't inline smi code before these stubs in the
    580   // optimizing code generator.
    581   if (code->kind() == Code::BINARY_OP_IC ||
    582       code->kind() == Code::COMPARE_IC) {
    583     __ nop();
    584   }
    585 }
    586 
    587 
    588 void LCodeGen::CallRuntime(const Runtime::Function* function,
    589                            int num_arguments,
    590                            LInstruction* instr) {
    591   ASSERT(instr != NULL);
    592   LPointerMap* pointers = instr->pointer_map();
    593   ASSERT(pointers != NULL);
    594   RecordPosition(pointers->position());
    595 
    596   __ CallRuntime(function, num_arguments);
    597   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
    598 }
    599 
    600 
    601 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
    602                                        int argc,
    603                                        LInstruction* instr) {
    604   __ CallRuntimeSaveDoubles(id);
    605   RecordSafepointWithRegisters(
    606       instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
    607 }
    608 
    609 
    610 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
    611                                                     Safepoint::DeoptMode mode) {
    612   if (!environment->HasBeenRegistered()) {
    613     // Physical stack frame layout:
    614     // -x ............. -4  0 ..................................... y
    615     // [incoming arguments] [spill slots] [pushed outgoing arguments]
    616 
    617     // Layout of the environment:
    618     // 0 ..................................................... size-1
    619     // [parameters] [locals] [expression stack including arguments]
    620 
    621     // Layout of the translation:
    622     // 0 ........................................................ size - 1 + 4
    623     // [expression stack including arguments] [locals] [4 words] [parameters]
    624     // |>------------  translation_size ------------<|
    625 
    626     int frame_count = 0;
    627     int jsframe_count = 0;
    628     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
    629       ++frame_count;
    630       if (e->frame_type() == JS_FUNCTION) {
    631         ++jsframe_count;
    632       }
    633     }
    634     Translation translation(&translations_, frame_count, jsframe_count);
    635     WriteTranslation(environment, &translation);
    636     int deoptimization_index = deoptimizations_.length();
    637     int pc_offset = masm()->pc_offset();
    638     environment->Register(deoptimization_index,
    639                           translation.index(),
    640                           (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
    641     deoptimizations_.Add(environment);
    642   }
    643 }
    644 
    645 
    646 void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
    647   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
    648   ASSERT(environment->HasBeenRegistered());
    649   int id = environment->deoptimization_index();
    650   Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
    651   if (entry == NULL) {
    652     Abort("bailout was not prepared");
    653     return;
    654   }
    655 
    656   ASSERT(FLAG_deopt_every_n_times < 2);  // Other values not supported on ARM.
    657 
    658   if (FLAG_deopt_every_n_times == 1 &&
    659       info_->shared_info()->opt_count() == id) {
    660     __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
    661     return;
    662   }
    663 
    664   if (FLAG_trap_on_deopt) __ stop("trap_on_deopt", cc);
    665 
    666   if (cc == al) {
    667     __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
    668   } else {
    669     // We often have several deopts to the same entry, reuse the last
    670     // jump entry if this is the case.
    671     if (deopt_jump_table_.is_empty() ||
    672         (deopt_jump_table_.last().address != entry)) {
    673       deopt_jump_table_.Add(JumpTableEntry(entry));
    674     }
    675     __ b(cc, &deopt_jump_table_.last().label);
    676   }
    677 }
    678 
    679 
    680 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
    681   int length = deoptimizations_.length();
    682   if (length == 0) return;
    683   Handle<DeoptimizationInputData> data =
    684       factory()->NewDeoptimizationInputData(length, TENURED);
    685 
    686   Handle<ByteArray> translations = translations_.CreateByteArray();
    687   data->SetTranslationByteArray(*translations);
    688   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
    689 
    690   Handle<FixedArray> literals =
    691       factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
    692   for (int i = 0; i < deoptimization_literals_.length(); i++) {
    693     literals->set(i, *deoptimization_literals_[i]);
    694   }
    695   data->SetLiteralArray(*literals);
    696 
    697   data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id()));
    698   data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
    699 
    700   // Populate the deoptimization entries.
    701   for (int i = 0; i < length; i++) {
    702     LEnvironment* env = deoptimizations_[i];
    703     data->SetAstId(i, Smi::FromInt(env->ast_id()));
    704     data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
    705     data->SetArgumentsStackHeight(i,
    706                                   Smi::FromInt(env->arguments_stack_height()));
    707     data->SetPc(i, Smi::FromInt(env->pc_offset()));
    708   }
    709   code->set_deoptimization_data(*data);
    710 }
    711 
    712 
    713 int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
    714   int result = deoptimization_literals_.length();
    715   for (int i = 0; i < deoptimization_literals_.length(); ++i) {
    716     if (deoptimization_literals_[i].is_identical_to(literal)) return i;
    717   }
    718   deoptimization_literals_.Add(literal);
    719   return result;
    720 }
    721 
    722 
    723 void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
    724   ASSERT(deoptimization_literals_.length() == 0);
    725 
    726   const ZoneList<Handle<JSFunction> >* inlined_closures =
    727       chunk()->inlined_closures();
    728 
    729   for (int i = 0, length = inlined_closures->length();
    730        i < length;
    731        i++) {
    732     DefineDeoptimizationLiteral(inlined_closures->at(i));
    733   }
    734 
    735   inlined_function_count_ = deoptimization_literals_.length();
    736 }
    737 
    738 
    739 void LCodeGen::RecordSafepointWithLazyDeopt(
    740     LInstruction* instr, SafepointMode safepoint_mode) {
    741   if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
    742     RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
    743   } else {
    744     ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
    745     RecordSafepointWithRegisters(
    746         instr->pointer_map(), 0, Safepoint::kLazyDeopt);
    747   }
    748 }
    749 
    750 
    751 void LCodeGen::RecordSafepoint(
    752     LPointerMap* pointers,
    753     Safepoint::Kind kind,
    754     int arguments,
    755     Safepoint::DeoptMode deopt_mode) {
    756   ASSERT(expected_safepoint_kind_ == kind);
    757 
    758   const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
    759   Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
    760       kind, arguments, deopt_mode);
    761   for (int i = 0; i < operands->length(); i++) {
    762     LOperand* pointer = operands->at(i);
    763     if (pointer->IsStackSlot()) {
    764       safepoint.DefinePointerSlot(pointer->index());
    765     } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
    766       safepoint.DefinePointerRegister(ToRegister(pointer));
    767     }
    768   }
    769   if (kind & Safepoint::kWithRegisters) {
    770     // Register cp always contains a pointer to the context.
    771     safepoint.DefinePointerRegister(cp);
    772   }
    773 }
    774 
    775 
    776 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
    777                                Safepoint::DeoptMode deopt_mode) {
    778   RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
    779 }
    780 
    781 
    782 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
    783   LPointerMap empty_pointers(RelocInfo::kNoPosition);
    784   RecordSafepoint(&empty_pointers, deopt_mode);
    785 }
    786 
    787 
    788 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
    789                                             int arguments,
    790                                             Safepoint::DeoptMode deopt_mode) {
    791   RecordSafepoint(
    792       pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
    793 }
    794 
    795 
    796 void LCodeGen::RecordSafepointWithRegistersAndDoubles(
    797     LPointerMap* pointers,
    798     int arguments,
    799     Safepoint::DeoptMode deopt_mode) {
    800   RecordSafepoint(
    801       pointers, Safepoint::kWithRegistersAndDoubles, arguments, deopt_mode);
    802 }
    803 
    804 
    805 void LCodeGen::RecordPosition(int position) {
    806   if (position == RelocInfo::kNoPosition) return;
    807   masm()->positions_recorder()->RecordPosition(position);
    808 }
    809 
    810 
    811 void LCodeGen::DoLabel(LLabel* label) {
    812   if (label->is_loop_header()) {
    813     Comment(";;; B%d - LOOP entry", label->block_id());
    814   } else {
    815     Comment(";;; B%d", label->block_id());
    816   }
    817   __ bind(label->label());
    818   current_block_ = label->block_id();
    819   DoGap(label);
    820 }
    821 
    822 
    823 void LCodeGen::DoParallelMove(LParallelMove* move) {
    824   resolver_.Resolve(move);
    825 }
    826 
    827 
    828 void LCodeGen::DoGap(LGap* gap) {
    829   for (int i = LGap::FIRST_INNER_POSITION;
    830        i <= LGap::LAST_INNER_POSITION;
    831        i++) {
    832     LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
    833     LParallelMove* move = gap->GetParallelMove(inner_pos);
    834     if (move != NULL) DoParallelMove(move);
    835   }
    836 }
    837 
    838 
    839 void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
    840   DoGap(instr);
    841 }
    842 
    843 
    844 void LCodeGen::DoParameter(LParameter* instr) {
    845   // Nothing to do.
    846 }
    847 
    848 
    849 void LCodeGen::DoCallStub(LCallStub* instr) {
    850   ASSERT(ToRegister(instr->result()).is(r0));
    851   switch (instr->hydrogen()->major_key()) {
    852     case CodeStub::RegExpConstructResult: {
    853       RegExpConstructResultStub stub;
    854       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    855       break;
    856     }
    857     case CodeStub::RegExpExec: {
    858       RegExpExecStub stub;
    859       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    860       break;
    861     }
    862     case CodeStub::SubString: {
    863       SubStringStub stub;
    864       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    865       break;
    866     }
    867     case CodeStub::NumberToString: {
    868       NumberToStringStub stub;
    869       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    870       break;
    871     }
    872     case CodeStub::StringAdd: {
    873       StringAddStub stub(NO_STRING_ADD_FLAGS);
    874       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    875       break;
    876     }
    877     case CodeStub::StringCompare: {
    878       StringCompareStub stub;
    879       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    880       break;
    881     }
    882     case CodeStub::TranscendentalCache: {
    883       __ ldr(r0, MemOperand(sp, 0));
    884       TranscendentalCacheStub stub(instr->transcendental_type(),
    885                                    TranscendentalCacheStub::TAGGED);
    886       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    887       break;
    888     }
    889     default:
    890       UNREACHABLE();
    891   }
    892 }
    893 
    894 
    895 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
    896   // Nothing to do.
    897 }
    898 
    899 
    900 void LCodeGen::DoModI(LModI* instr) {
    901   if (instr->hydrogen()->HasPowerOf2Divisor()) {
    902     Register dividend = ToRegister(instr->InputAt(0));
    903     Register result = ToRegister(instr->result());
    904 
    905     int32_t divisor =
    906         HConstant::cast(instr->hydrogen()->right())->Integer32Value();
    907 
    908     if (divisor < 0) divisor = -divisor;
    909 
    910     Label positive_dividend, done;
    911     __ cmp(dividend, Operand(0));
    912     __ b(pl, &positive_dividend);
    913     __ rsb(result, dividend, Operand(0));
    914     __ and_(result, result, Operand(divisor - 1), SetCC);
    915     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    916       DeoptimizeIf(eq, instr->environment());
    917     }
    918     __ rsb(result, result, Operand(0));
    919     __ b(&done);
    920     __ bind(&positive_dividend);
    921     __ and_(result, dividend, Operand(divisor - 1));
    922     __ bind(&done);
    923     return;
    924   }
    925 
    926   // These registers hold untagged 32 bit values.
    927   Register left = ToRegister(instr->InputAt(0));
    928   Register right = ToRegister(instr->InputAt(1));
    929   Register result = ToRegister(instr->result());
    930 
    931   Register scratch = scratch0();
    932   Register scratch2 = ToRegister(instr->TempAt(0));
    933   DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1));
    934   DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2));
    935   DwVfpRegister quotient = double_scratch0();
    936 
    937   ASSERT(!dividend.is(divisor));
    938   ASSERT(!dividend.is(quotient));
    939   ASSERT(!divisor.is(quotient));
    940   ASSERT(!scratch.is(left));
    941   ASSERT(!scratch.is(right));
    942   ASSERT(!scratch.is(result));
    943 
    944   Label done, vfp_modulo, both_positive, right_negative;
    945 
    946   // Check for x % 0.
    947   if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
    948     __ cmp(right, Operand(0));
    949     DeoptimizeIf(eq, instr->environment());
    950   }
    951 
    952   __ Move(result, left);
    953 
    954   // (0 % x) must yield 0 (if x is finite, which is the case here).
    955   __ cmp(left, Operand(0));
    956   __ b(eq, &done);
    957   // Preload right in a vfp register.
    958   __ vmov(divisor.low(), right);
    959   __ b(lt, &vfp_modulo);
    960 
    961   __ cmp(left, Operand(right));
    962   __ b(lt, &done);
    963 
    964   // Check for (positive) power of two on the right hand side.
    965   __ JumpIfNotPowerOfTwoOrZeroAndNeg(right,
    966                                      scratch,
    967                                      &right_negative,
    968                                      &both_positive);
    969   // Perform modulo operation (scratch contains right - 1).
    970   __ and_(result, scratch, Operand(left));
    971   __ b(&done);
    972 
    973   __ bind(&right_negative);
    974   // Negate right. The sign of the divisor does not matter.
    975   __ rsb(right, right, Operand(0));
    976 
    977   __ bind(&both_positive);
    978   const int kUnfolds = 3;
    979   // If the right hand side is smaller than the (nonnegative)
    980   // left hand side, the left hand side is the result.
    981   // Else try a few subtractions of the left hand side.
    982   __ mov(scratch, left);
    983   for (int i = 0; i < kUnfolds; i++) {
    984     // Check if the left hand side is less or equal than the
    985     // the right hand side.
    986     __ cmp(scratch, Operand(right));
    987     __ mov(result, scratch, LeaveCC, lt);
    988     __ b(lt, &done);
    989     // If not, reduce the left hand side by the right hand
    990     // side and check again.
    991     if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
    992   }
    993 
    994   __ bind(&vfp_modulo);
    995   // Load the arguments in VFP registers.
    996   // The divisor value is preloaded before. Be careful that 'right' is only live
    997   // on entry.
    998   __ vmov(dividend.low(), left);
    999   // From here on don't use right as it may have been reallocated (for example
   1000   // to scratch2).
   1001   right = no_reg;
   1002 
   1003   __ vcvt_f64_s32(dividend, dividend.low());
   1004   __ vcvt_f64_s32(divisor, divisor.low());
   1005 
   1006   // We do not care about the sign of the divisor.
   1007   __ vabs(divisor, divisor);
   1008   // Compute the quotient and round it to a 32bit integer.
   1009   __ vdiv(quotient, dividend, divisor);
   1010   __ vcvt_s32_f64(quotient.low(), quotient);
   1011   __ vcvt_f64_s32(quotient, quotient.low());
   1012 
   1013   // Compute the remainder in result.
   1014   DwVfpRegister double_scratch = dividend;
   1015   __ vmul(double_scratch, divisor, quotient);
   1016   __ vcvt_s32_f64(double_scratch.low(), double_scratch);
   1017   __ vmov(scratch, double_scratch.low());
   1018 
   1019   if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1020     __ sub(result, left, scratch);
   1021   } else {
   1022     Label ok;
   1023     // Check for -0.
   1024     __ sub(scratch2, left, scratch, SetCC);
   1025     __ b(ne, &ok);
   1026     __ cmp(left, Operand(0));
   1027     DeoptimizeIf(mi, instr->environment());
   1028     __ bind(&ok);
   1029     // Load the result and we are done.
   1030     __ mov(result, scratch2);
   1031   }
   1032 
   1033   __ bind(&done);
   1034 }
   1035 
   1036 
   1037 void LCodeGen::DoDivI(LDivI* instr) {
   1038   class DeferredDivI: public LDeferredCode {
   1039    public:
   1040     DeferredDivI(LCodeGen* codegen, LDivI* instr)
   1041         : LDeferredCode(codegen), instr_(instr) { }
   1042     virtual void Generate() {
   1043       codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV);
   1044     }
   1045     virtual LInstruction* instr() { return instr_; }
   1046    private:
   1047     LDivI* instr_;
   1048   };
   1049 
   1050   const Register left = ToRegister(instr->InputAt(0));
   1051   const Register right = ToRegister(instr->InputAt(1));
   1052   const Register scratch = scratch0();
   1053   const Register result = ToRegister(instr->result());
   1054 
   1055   // Check for x / 0.
   1056   if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
   1057     __ cmp(right, Operand(0));
   1058     DeoptimizeIf(eq, instr->environment());
   1059   }
   1060 
   1061   // Check for (0 / -x) that will produce negative zero.
   1062   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1063     Label left_not_zero;
   1064     __ cmp(left, Operand(0));
   1065     __ b(ne, &left_not_zero);
   1066     __ cmp(right, Operand(0));
   1067     DeoptimizeIf(mi, instr->environment());
   1068     __ bind(&left_not_zero);
   1069   }
   1070 
   1071   // Check for (-kMinInt / -1).
   1072   if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
   1073     Label left_not_min_int;
   1074     __ cmp(left, Operand(kMinInt));
   1075     __ b(ne, &left_not_min_int);
   1076     __ cmp(right, Operand(-1));
   1077     DeoptimizeIf(eq, instr->environment());
   1078     __ bind(&left_not_min_int);
   1079   }
   1080 
   1081   Label done, deoptimize;
   1082   // Test for a few common cases first.
   1083   __ cmp(right, Operand(1));
   1084   __ mov(result, left, LeaveCC, eq);
   1085   __ b(eq, &done);
   1086 
   1087   __ cmp(right, Operand(2));
   1088   __ tst(left, Operand(1), eq);
   1089   __ mov(result, Operand(left, ASR, 1), LeaveCC, eq);
   1090   __ b(eq, &done);
   1091 
   1092   __ cmp(right, Operand(4));
   1093   __ tst(left, Operand(3), eq);
   1094   __ mov(result, Operand(left, ASR, 2), LeaveCC, eq);
   1095   __ b(eq, &done);
   1096 
   1097   // Call the stub. The numbers in r0 and r1 have
   1098   // to be tagged to Smis. If that is not possible, deoptimize.
   1099   DeferredDivI* deferred = new DeferredDivI(this, instr);
   1100 
   1101   __ TrySmiTag(left, &deoptimize, scratch);
   1102   __ TrySmiTag(right, &deoptimize, scratch);
   1103 
   1104   __ b(al, deferred->entry());
   1105   __ bind(deferred->exit());
   1106 
   1107   // If the result in r0 is a Smi, untag it, else deoptimize.
   1108   __ JumpIfNotSmi(result, &deoptimize);
   1109   __ SmiUntag(result);
   1110   __ b(&done);
   1111 
   1112   __ bind(&deoptimize);
   1113   DeoptimizeIf(al, instr->environment());
   1114   __ bind(&done);
   1115 }
   1116 
   1117 
   1118 template<int T>
   1119 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
   1120                                       Token::Value op) {
   1121   Register left = ToRegister(instr->InputAt(0));
   1122   Register right = ToRegister(instr->InputAt(1));
   1123 
   1124   PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles);
   1125   // Move left to r1 and right to r0 for the stub call.
   1126   if (left.is(r1)) {
   1127     __ Move(r0, right);
   1128   } else if (left.is(r0) && right.is(r1)) {
   1129     __ Swap(r0, r1, r2);
   1130   } else if (left.is(r0)) {
   1131     ASSERT(!right.is(r1));
   1132     __ mov(r1, r0);
   1133     __ mov(r0, right);
   1134   } else {
   1135     ASSERT(!left.is(r0) && !right.is(r0));
   1136     __ mov(r0, right);
   1137     __ mov(r1, left);
   1138   }
   1139   BinaryOpStub stub(op, OVERWRITE_LEFT);
   1140   __ CallStub(&stub);
   1141   RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
   1142                                          0,
   1143                                          Safepoint::kNoLazyDeopt);
   1144   // Overwrite the stored value of r0 with the result of the stub.
   1145   __ StoreToSafepointRegistersAndDoublesSlot(r0, r0);
   1146 }
   1147 
   1148 
   1149 void LCodeGen::DoMulI(LMulI* instr) {
   1150   Register scratch = scratch0();
   1151   Register result = ToRegister(instr->result());
   1152   // Note that result may alias left.
   1153   Register left = ToRegister(instr->InputAt(0));
   1154   LOperand* right_op = instr->InputAt(1);
   1155 
   1156   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
   1157   bool bailout_on_minus_zero =
   1158     instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
   1159 
   1160   if (right_op->IsConstantOperand() && !can_overflow) {
   1161     // Use optimized code for specific constants.
   1162     int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
   1163 
   1164     if (bailout_on_minus_zero && (constant < 0)) {
   1165       // The case of a null constant will be handled separately.
   1166       // If constant is negative and left is null, the result should be -0.
   1167       __ cmp(left, Operand(0));
   1168       DeoptimizeIf(eq, instr->environment());
   1169     }
   1170 
   1171     switch (constant) {
   1172       case -1:
   1173         __ rsb(result, left, Operand(0));
   1174         break;
   1175       case 0:
   1176         if (bailout_on_minus_zero) {
   1177           // If left is strictly negative and the constant is null, the
   1178           // result is -0. Deoptimize if required, otherwise return 0.
   1179           __ cmp(left, Operand(0));
   1180           DeoptimizeIf(mi, instr->environment());
   1181         }
   1182         __ mov(result, Operand(0));
   1183         break;
   1184       case 1:
   1185         __ Move(result, left);
   1186         break;
   1187       default:
   1188         // Multiplying by powers of two and powers of two plus or minus
   1189         // one can be done faster with shifted operands.
   1190         // For other constants we emit standard code.
   1191         int32_t mask = constant >> 31;
   1192         uint32_t constant_abs = (constant + mask) ^ mask;
   1193 
   1194         if (IsPowerOf2(constant_abs) ||
   1195             IsPowerOf2(constant_abs - 1) ||
   1196             IsPowerOf2(constant_abs + 1)) {
   1197           if (IsPowerOf2(constant_abs)) {
   1198             int32_t shift = WhichPowerOf2(constant_abs);
   1199             __ mov(result, Operand(left, LSL, shift));
   1200           } else if (IsPowerOf2(constant_abs - 1)) {
   1201             int32_t shift = WhichPowerOf2(constant_abs - 1);
   1202             __ add(result, left, Operand(left, LSL, shift));
   1203           } else if (IsPowerOf2(constant_abs + 1)) {
   1204             int32_t shift = WhichPowerOf2(constant_abs + 1);
   1205             __ rsb(result, left, Operand(left, LSL, shift));
   1206           }
   1207 
   1208           // Correct the sign of the result is the constant is negative.
   1209           if (constant < 0)  __ rsb(result, result, Operand(0));
   1210 
   1211         } else {
   1212           // Generate standard code.
   1213           __ mov(ip, Operand(constant));
   1214           __ mul(result, left, ip);
   1215         }
   1216     }
   1217 
   1218   } else {
   1219     Register right = EmitLoadRegister(right_op, scratch);
   1220     if (bailout_on_minus_zero) {
   1221       __ orr(ToRegister(instr->TempAt(0)), left, right);
   1222     }
   1223 
   1224     if (can_overflow) {
   1225       // scratch:result = left * right.
   1226       __ smull(result, scratch, left, right);
   1227       __ cmp(scratch, Operand(result, ASR, 31));
   1228       DeoptimizeIf(ne, instr->environment());
   1229     } else {
   1230       __ mul(result, left, right);
   1231     }
   1232 
   1233     if (bailout_on_minus_zero) {
   1234       // Bail out if the result is supposed to be negative zero.
   1235       Label done;
   1236       __ cmp(result, Operand(0));
   1237       __ b(ne, &done);
   1238       __ cmp(ToRegister(instr->TempAt(0)), Operand(0));
   1239       DeoptimizeIf(mi, instr->environment());
   1240       __ bind(&done);
   1241     }
   1242   }
   1243 }
   1244 
   1245 
   1246 void LCodeGen::DoBitI(LBitI* instr) {
   1247   LOperand* left_op = instr->InputAt(0);
   1248   LOperand* right_op = instr->InputAt(1);
   1249   ASSERT(left_op->IsRegister());
   1250   Register left = ToRegister(left_op);
   1251   Register result = ToRegister(instr->result());
   1252   Operand right(no_reg);
   1253 
   1254   if (right_op->IsStackSlot() || right_op->IsArgument()) {
   1255     right = Operand(EmitLoadRegister(right_op, ip));
   1256   } else {
   1257     ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
   1258     right = ToOperand(right_op);
   1259   }
   1260 
   1261   switch (instr->op()) {
   1262     case Token::BIT_AND:
   1263       __ and_(result, left, right);
   1264       break;
   1265     case Token::BIT_OR:
   1266       __ orr(result, left, right);
   1267       break;
   1268     case Token::BIT_XOR:
   1269       __ eor(result, left, right);
   1270       break;
   1271     default:
   1272       UNREACHABLE();
   1273       break;
   1274   }
   1275 }
   1276 
   1277 
   1278 void LCodeGen::DoShiftI(LShiftI* instr) {
   1279   // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so
   1280   // result may alias either of them.
   1281   LOperand* right_op = instr->InputAt(1);
   1282   Register left = ToRegister(instr->InputAt(0));
   1283   Register result = ToRegister(instr->result());
   1284   Register scratch = scratch0();
   1285   if (right_op->IsRegister()) {
   1286     // Mask the right_op operand.
   1287     __ and_(scratch, ToRegister(right_op), Operand(0x1F));
   1288     switch (instr->op()) {
   1289       case Token::SAR:
   1290         __ mov(result, Operand(left, ASR, scratch));
   1291         break;
   1292       case Token::SHR:
   1293         if (instr->can_deopt()) {
   1294           __ mov(result, Operand(left, LSR, scratch), SetCC);
   1295           DeoptimizeIf(mi, instr->environment());
   1296         } else {
   1297           __ mov(result, Operand(left, LSR, scratch));
   1298         }
   1299         break;
   1300       case Token::SHL:
   1301         __ mov(result, Operand(left, LSL, scratch));
   1302         break;
   1303       default:
   1304         UNREACHABLE();
   1305         break;
   1306     }
   1307   } else {
   1308     // Mask the right_op operand.
   1309     int value = ToInteger32(LConstantOperand::cast(right_op));
   1310     uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
   1311     switch (instr->op()) {
   1312       case Token::SAR:
   1313         if (shift_count != 0) {
   1314           __ mov(result, Operand(left, ASR, shift_count));
   1315         } else {
   1316           __ Move(result, left);
   1317         }
   1318         break;
   1319       case Token::SHR:
   1320         if (shift_count != 0) {
   1321           __ mov(result, Operand(left, LSR, shift_count));
   1322         } else {
   1323           if (instr->can_deopt()) {
   1324             __ tst(left, Operand(0x80000000));
   1325             DeoptimizeIf(ne, instr->environment());
   1326           }
   1327           __ Move(result, left);
   1328         }
   1329         break;
   1330       case Token::SHL:
   1331         if (shift_count != 0) {
   1332           __ mov(result, Operand(left, LSL, shift_count));
   1333         } else {
   1334           __ Move(result, left);
   1335         }
   1336         break;
   1337       default:
   1338         UNREACHABLE();
   1339         break;
   1340     }
   1341   }
   1342 }
   1343 
   1344 
   1345 void LCodeGen::DoSubI(LSubI* instr) {
   1346   LOperand* left = instr->InputAt(0);
   1347   LOperand* right = instr->InputAt(1);
   1348   LOperand* result = instr->result();
   1349   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
   1350   SBit set_cond = can_overflow ? SetCC : LeaveCC;
   1351 
   1352   if (right->IsStackSlot() || right->IsArgument()) {
   1353     Register right_reg = EmitLoadRegister(right, ip);
   1354     __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
   1355   } else {
   1356     ASSERT(right->IsRegister() || right->IsConstantOperand());
   1357     __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
   1358   }
   1359 
   1360   if (can_overflow) {
   1361     DeoptimizeIf(vs, instr->environment());
   1362   }
   1363 }
   1364 
   1365 
   1366 void LCodeGen::DoConstantI(LConstantI* instr) {
   1367   ASSERT(instr->result()->IsRegister());
   1368   __ mov(ToRegister(instr->result()), Operand(instr->value()));
   1369 }
   1370 
   1371 
   1372 void LCodeGen::DoConstantD(LConstantD* instr) {
   1373   ASSERT(instr->result()->IsDoubleRegister());
   1374   DwVfpRegister result = ToDoubleRegister(instr->result());
   1375   double v = instr->value();
   1376   __ Vmov(result, v);
   1377 }
   1378 
   1379 
   1380 void LCodeGen::DoConstantT(LConstantT* instr) {
   1381   Handle<Object> value = instr->value();
   1382   if (value->IsSmi()) {
   1383     __ mov(ToRegister(instr->result()), Operand(value));
   1384   } else {
   1385     __ LoadHeapObject(ToRegister(instr->result()),
   1386                       Handle<HeapObject>::cast(value));
   1387   }
   1388 }
   1389 
   1390 
   1391 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
   1392   Register result = ToRegister(instr->result());
   1393   Register array = ToRegister(instr->InputAt(0));
   1394   __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
   1395 }
   1396 
   1397 
   1398 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
   1399   Register result = ToRegister(instr->result());
   1400   Register array = ToRegister(instr->InputAt(0));
   1401   __ ldr(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset));
   1402 }
   1403 
   1404 
   1405 void LCodeGen::DoElementsKind(LElementsKind* instr) {
   1406   Register result = ToRegister(instr->result());
   1407   Register input = ToRegister(instr->InputAt(0));
   1408 
   1409   // Load map into |result|.
   1410   __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset));
   1411   // Load the map's "bit field 2" into |result|. We only need the first byte,
   1412   // but the following bit field extraction takes care of that anyway.
   1413   __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset));
   1414   // Retrieve elements_kind from bit field 2.
   1415   __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount);
   1416 }
   1417 
   1418 
   1419 void LCodeGen::DoValueOf(LValueOf* instr) {
   1420   Register input = ToRegister(instr->InputAt(0));
   1421   Register result = ToRegister(instr->result());
   1422   Register map = ToRegister(instr->TempAt(0));
   1423   Label done;
   1424 
   1425   // If the object is a smi return the object.
   1426   __ tst(input, Operand(kSmiTagMask));
   1427   __ Move(result, input, eq);
   1428   __ b(eq, &done);
   1429 
   1430   // If the object is not a value type, return the object.
   1431   __ CompareObjectType(input, map, map, JS_VALUE_TYPE);
   1432   __ Move(result, input, ne);
   1433   __ b(ne, &done);
   1434   __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset));
   1435 
   1436   __ bind(&done);
   1437 }
   1438 
   1439 
   1440 void LCodeGen::DoDateField(LDateField* instr) {
   1441   Register object = ToRegister(instr->InputAt(0));
   1442   Register result = ToRegister(instr->result());
   1443   Register scratch = ToRegister(instr->TempAt(0));
   1444   Smi* index = instr->index();
   1445   Label runtime, done;
   1446   ASSERT(object.is(result));
   1447   ASSERT(object.is(r0));
   1448   ASSERT(!scratch.is(scratch0()));
   1449   ASSERT(!scratch.is(object));
   1450 
   1451 #ifdef DEBUG
   1452   __ AbortIfSmi(object);
   1453   __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
   1454   __ Assert(eq, "Trying to get date field from non-date.");
   1455 #endif
   1456 
   1457   if (index->value() == 0) {
   1458     __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
   1459   } else {
   1460     if (index->value() < JSDate::kFirstUncachedField) {
   1461       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
   1462       __ mov(scratch, Operand(stamp));
   1463       __ ldr(scratch, MemOperand(scratch));
   1464       __ ldr(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
   1465       __ cmp(scratch, scratch0());
   1466       __ b(ne, &runtime);
   1467       __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset +
   1468                                              kPointerSize * index->value()));
   1469       __ jmp(&done);
   1470     }
   1471     __ bind(&runtime);
   1472     __ PrepareCallCFunction(2, scratch);
   1473     __ mov(r1, Operand(index));
   1474     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
   1475     __ bind(&done);
   1476   }
   1477 }
   1478 
   1479 
   1480 void LCodeGen::DoBitNotI(LBitNotI* instr) {
   1481   Register input = ToRegister(instr->InputAt(0));
   1482   Register result = ToRegister(instr->result());
   1483   __ mvn(result, Operand(input));
   1484 }
   1485 
   1486 
   1487 void LCodeGen::DoThrow(LThrow* instr) {
   1488   Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
   1489   __ push(input_reg);
   1490   CallRuntime(Runtime::kThrow, 1, instr);
   1491 
   1492   if (FLAG_debug_code) {
   1493     __ stop("Unreachable code.");
   1494   }
   1495 }
   1496 
   1497 
   1498 void LCodeGen::DoAddI(LAddI* instr) {
   1499   LOperand* left = instr->InputAt(0);
   1500   LOperand* right = instr->InputAt(1);
   1501   LOperand* result = instr->result();
   1502   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
   1503   SBit set_cond = can_overflow ? SetCC : LeaveCC;
   1504 
   1505   if (right->IsStackSlot() || right->IsArgument()) {
   1506     Register right_reg = EmitLoadRegister(right, ip);
   1507     __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
   1508   } else {
   1509     ASSERT(right->IsRegister() || right->IsConstantOperand());
   1510     __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
   1511   }
   1512 
   1513   if (can_overflow) {
   1514     DeoptimizeIf(vs, instr->environment());
   1515   }
   1516 }
   1517 
   1518 
   1519 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
   1520   DoubleRegister left = ToDoubleRegister(instr->InputAt(0));
   1521   DoubleRegister right = ToDoubleRegister(instr->InputAt(1));
   1522   DoubleRegister result = ToDoubleRegister(instr->result());
   1523   switch (instr->op()) {
   1524     case Token::ADD:
   1525       __ vadd(result, left, right);
   1526       break;
   1527     case Token::SUB:
   1528       __ vsub(result, left, right);
   1529       break;
   1530     case Token::MUL:
   1531       __ vmul(result, left, right);
   1532       break;
   1533     case Token::DIV:
   1534       __ vdiv(result, left, right);
   1535       break;
   1536     case Token::MOD: {
   1537       // Save r0-r3 on the stack.
   1538       __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
   1539 
   1540       __ PrepareCallCFunction(0, 2, scratch0());
   1541       __ SetCallCDoubleArguments(left, right);
   1542       __ CallCFunction(
   1543           ExternalReference::double_fp_operation(Token::MOD, isolate()),
   1544           0, 2);
   1545       // Move the result in the double result register.
   1546       __ GetCFunctionDoubleResult(result);
   1547 
   1548       // Restore r0-r3.
   1549       __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
   1550       break;
   1551     }
   1552     default:
   1553       UNREACHABLE();
   1554       break;
   1555   }
   1556 }
   1557 
   1558 
   1559 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
   1560   ASSERT(ToRegister(instr->InputAt(0)).is(r1));
   1561   ASSERT(ToRegister(instr->InputAt(1)).is(r0));
   1562   ASSERT(ToRegister(instr->result()).is(r0));
   1563 
   1564   BinaryOpStub stub(instr->op(), NO_OVERWRITE);
   1565   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   1566   __ nop();  // Signals no inlined code.
   1567 }
   1568 
   1569 
   1570 int LCodeGen::GetNextEmittedBlock(int block) {
   1571   for (int i = block + 1; i < graph()->blocks()->length(); ++i) {
   1572     LLabel* label = chunk_->GetLabel(i);
   1573     if (!label->HasReplacement()) return i;
   1574   }
   1575   return -1;
   1576 }
   1577 
   1578 
   1579 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) {
   1580   int next_block = GetNextEmittedBlock(current_block_);
   1581   right_block = chunk_->LookupDestination(right_block);
   1582   left_block = chunk_->LookupDestination(left_block);
   1583 
   1584   if (right_block == left_block) {
   1585     EmitGoto(left_block);
   1586   } else if (left_block == next_block) {
   1587     __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
   1588   } else if (right_block == next_block) {
   1589     __ b(cc, chunk_->GetAssemblyLabel(left_block));
   1590   } else {
   1591     __ b(cc, chunk_->GetAssemblyLabel(left_block));
   1592     __ b(chunk_->GetAssemblyLabel(right_block));
   1593   }
   1594 }
   1595 
   1596 
   1597 void LCodeGen::DoBranch(LBranch* instr) {
   1598   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1599   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1600 
   1601   Representation r = instr->hydrogen()->value()->representation();
   1602   if (r.IsInteger32()) {
   1603     Register reg = ToRegister(instr->InputAt(0));
   1604     __ cmp(reg, Operand(0));
   1605     EmitBranch(true_block, false_block, ne);
   1606   } else if (r.IsDouble()) {
   1607     DoubleRegister reg = ToDoubleRegister(instr->InputAt(0));
   1608     Register scratch = scratch0();
   1609 
   1610     // Test the double value. Zero and NaN are false.
   1611     __ VFPCompareAndLoadFlags(reg, 0.0, scratch);
   1612     __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit));
   1613     EmitBranch(true_block, false_block, eq);
   1614   } else {
   1615     ASSERT(r.IsTagged());
   1616     Register reg = ToRegister(instr->InputAt(0));
   1617     HType type = instr->hydrogen()->value()->type();
   1618     if (type.IsBoolean()) {
   1619       __ CompareRoot(reg, Heap::kTrueValueRootIndex);
   1620       EmitBranch(true_block, false_block, eq);
   1621     } else if (type.IsSmi()) {
   1622       __ cmp(reg, Operand(0));
   1623       EmitBranch(true_block, false_block, ne);
   1624     } else {
   1625       Label* true_label = chunk_->GetAssemblyLabel(true_block);
   1626       Label* false_label = chunk_->GetAssemblyLabel(false_block);
   1627 
   1628       ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
   1629       // Avoid deopts in the case where we've never executed this path before.
   1630       if (expected.IsEmpty()) expected = ToBooleanStub::all_types();
   1631 
   1632       if (expected.Contains(ToBooleanStub::UNDEFINED)) {
   1633         // undefined -> false.
   1634         __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
   1635         __ b(eq, false_label);
   1636       }
   1637       if (expected.Contains(ToBooleanStub::BOOLEAN)) {
   1638         // Boolean -> its value.
   1639         __ CompareRoot(reg, Heap::kTrueValueRootIndex);
   1640         __ b(eq, true_label);
   1641         __ CompareRoot(reg, Heap::kFalseValueRootIndex);
   1642         __ b(eq, false_label);
   1643       }
   1644       if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
   1645         // 'null' -> false.
   1646         __ CompareRoot(reg, Heap::kNullValueRootIndex);
   1647         __ b(eq, false_label);
   1648       }
   1649 
   1650       if (expected.Contains(ToBooleanStub::SMI)) {
   1651         // Smis: 0 -> false, all other -> true.
   1652         __ cmp(reg, Operand(0));
   1653         __ b(eq, false_label);
   1654         __ JumpIfSmi(reg, true_label);
   1655       } else if (expected.NeedsMap()) {
   1656         // If we need a map later and have a Smi -> deopt.
   1657         __ tst(reg, Operand(kSmiTagMask));
   1658         DeoptimizeIf(eq, instr->environment());
   1659       }
   1660 
   1661       const Register map = scratch0();
   1662       if (expected.NeedsMap()) {
   1663         __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset));
   1664 
   1665         if (expected.CanBeUndetectable()) {
   1666           // Undetectable -> false.
   1667           __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
   1668           __ tst(ip, Operand(1 << Map::kIsUndetectable));
   1669           __ b(ne, false_label);
   1670         }
   1671       }
   1672 
   1673       if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
   1674         // spec object -> true.
   1675         __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
   1676         __ b(ge, true_label);
   1677       }
   1678 
   1679       if (expected.Contains(ToBooleanStub::STRING)) {
   1680         // String value -> false iff empty.
   1681         Label not_string;
   1682         __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
   1683         __ b(ge, &not_string);
   1684         __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset));
   1685         __ cmp(ip, Operand(0));
   1686         __ b(ne, true_label);
   1687         __ b(false_label);
   1688         __ bind(&not_string);
   1689       }
   1690 
   1691       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
   1692         // heap number -> false iff +0, -0, or NaN.
   1693         DoubleRegister dbl_scratch = double_scratch0();
   1694         Label not_heap_number;
   1695         __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
   1696         __ b(ne, &not_heap_number);
   1697         __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
   1698         __ VFPCompareAndSetFlags(dbl_scratch, 0.0);
   1699         __ b(vs, false_label);  // NaN -> false.
   1700         __ b(eq, false_label);  // +0, -0 -> false.
   1701         __ b(true_label);
   1702         __ bind(&not_heap_number);
   1703       }
   1704 
   1705       // We've seen something for the first time -> deopt.
   1706       DeoptimizeIf(al, instr->environment());
   1707     }
   1708   }
   1709 }
   1710 
   1711 
   1712 void LCodeGen::EmitGoto(int block) {
   1713   block = chunk_->LookupDestination(block);
   1714   int next_block = GetNextEmittedBlock(current_block_);
   1715   if (block != next_block) {
   1716     __ jmp(chunk_->GetAssemblyLabel(block));
   1717   }
   1718 }
   1719 
   1720 
   1721 void LCodeGen::DoGoto(LGoto* instr) {
   1722   EmitGoto(instr->block_id());
   1723 }
   1724 
   1725 
   1726 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
   1727   Condition cond = kNoCondition;
   1728   switch (op) {
   1729     case Token::EQ:
   1730     case Token::EQ_STRICT:
   1731       cond = eq;
   1732       break;
   1733     case Token::LT:
   1734       cond = is_unsigned ? lo : lt;
   1735       break;
   1736     case Token::GT:
   1737       cond = is_unsigned ? hi : gt;
   1738       break;
   1739     case Token::LTE:
   1740       cond = is_unsigned ? ls : le;
   1741       break;
   1742     case Token::GTE:
   1743       cond = is_unsigned ? hs : ge;
   1744       break;
   1745     case Token::IN:
   1746     case Token::INSTANCEOF:
   1747     default:
   1748       UNREACHABLE();
   1749   }
   1750   return cond;
   1751 }
   1752 
   1753 
   1754 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
   1755   LOperand* left = instr->InputAt(0);
   1756   LOperand* right = instr->InputAt(1);
   1757   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1758   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1759   Condition cond = TokenToCondition(instr->op(), false);
   1760 
   1761   if (left->IsConstantOperand() && right->IsConstantOperand()) {
   1762     // We can statically evaluate the comparison.
   1763     double left_val = ToDouble(LConstantOperand::cast(left));
   1764     double right_val = ToDouble(LConstantOperand::cast(right));
   1765     int next_block =
   1766       EvalComparison(instr->op(), left_val, right_val) ? true_block
   1767                                                        : false_block;
   1768     EmitGoto(next_block);
   1769   } else {
   1770     if (instr->is_double()) {
   1771       // Compare left and right operands as doubles and load the
   1772       // resulting flags into the normal status register.
   1773       __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right));
   1774       // If a NaN is involved, i.e. the result is unordered (V set),
   1775       // jump to false block label.
   1776       __ b(vs, chunk_->GetAssemblyLabel(false_block));
   1777     } else {
   1778       if (right->IsConstantOperand()) {
   1779         __ cmp(ToRegister(left),
   1780                Operand(ToInteger32(LConstantOperand::cast(right))));
   1781       } else if (left->IsConstantOperand()) {
   1782         __ cmp(ToRegister(right),
   1783                Operand(ToInteger32(LConstantOperand::cast(left))));
   1784         // We transposed the operands. Reverse the condition.
   1785         cond = ReverseCondition(cond);
   1786       } else {
   1787         __ cmp(ToRegister(left), ToRegister(right));
   1788       }
   1789     }
   1790     EmitBranch(true_block, false_block, cond);
   1791   }
   1792 }
   1793 
   1794 
   1795 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
   1796   Register left = ToRegister(instr->InputAt(0));
   1797   Register right = ToRegister(instr->InputAt(1));
   1798   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1799   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1800 
   1801   __ cmp(left, Operand(right));
   1802   EmitBranch(true_block, false_block, eq);
   1803 }
   1804 
   1805 
   1806 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
   1807   Register left = ToRegister(instr->InputAt(0));
   1808   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1809   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1810 
   1811   __ cmp(left, Operand(instr->hydrogen()->right()));
   1812   EmitBranch(true_block, false_block, eq);
   1813 }
   1814 
   1815 
   1816 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) {
   1817   Register scratch = scratch0();
   1818   Register reg = ToRegister(instr->InputAt(0));
   1819   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1820 
   1821   // If the expression is known to be untagged or a smi, then it's definitely
   1822   // not null, and it can't be a an undetectable object.
   1823   if (instr->hydrogen()->representation().IsSpecialization() ||
   1824       instr->hydrogen()->type().IsSmi()) {
   1825     EmitGoto(false_block);
   1826     return;
   1827   }
   1828 
   1829   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1830   Heap::RootListIndex nil_value = instr->nil() == kNullValue ?
   1831       Heap::kNullValueRootIndex :
   1832       Heap::kUndefinedValueRootIndex;
   1833   __ LoadRoot(ip, nil_value);
   1834   __ cmp(reg, ip);
   1835   if (instr->kind() == kStrictEquality) {
   1836     EmitBranch(true_block, false_block, eq);
   1837   } else {
   1838     Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ?
   1839         Heap::kUndefinedValueRootIndex :
   1840         Heap::kNullValueRootIndex;
   1841     Label* true_label = chunk_->GetAssemblyLabel(true_block);
   1842     Label* false_label = chunk_->GetAssemblyLabel(false_block);
   1843     __ b(eq, true_label);
   1844     __ LoadRoot(ip, other_nil_value);
   1845     __ cmp(reg, ip);
   1846     __ b(eq, true_label);
   1847     __ JumpIfSmi(reg, false_label);
   1848     // Check for undetectable objects by looking in the bit field in
   1849     // the map. The object has already been smi checked.
   1850     __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
   1851     __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
   1852     __ tst(scratch, Operand(1 << Map::kIsUndetectable));
   1853     EmitBranch(true_block, false_block, ne);
   1854   }
   1855 }
   1856 
   1857 
   1858 Condition LCodeGen::EmitIsObject(Register input,
   1859                                  Register temp1,
   1860                                  Label* is_not_object,
   1861                                  Label* is_object) {
   1862   Register temp2 = scratch0();
   1863   __ JumpIfSmi(input, is_not_object);
   1864 
   1865   __ LoadRoot(temp2, Heap::kNullValueRootIndex);
   1866   __ cmp(input, temp2);
   1867   __ b(eq, is_object);
   1868 
   1869   // Load map.
   1870   __ ldr(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
   1871   // Undetectable objects behave like undefined.
   1872   __ ldrb(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
   1873   __ tst(temp2, Operand(1 << Map::kIsUndetectable));
   1874   __ b(ne, is_not_object);
   1875 
   1876   // Load instance type and check that it is in object type range.
   1877   __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
   1878   __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
   1879   __ b(lt, is_not_object);
   1880   __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
   1881   return le;
   1882 }
   1883 
   1884 
   1885 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
   1886   Register reg = ToRegister(instr->InputAt(0));
   1887   Register temp1 = ToRegister(instr->TempAt(0));
   1888 
   1889   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1890   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1891   Label* true_label = chunk_->GetAssemblyLabel(true_block);
   1892   Label* false_label = chunk_->GetAssemblyLabel(false_block);
   1893 
   1894   Condition true_cond =
   1895       EmitIsObject(reg, temp1, false_label, true_label);
   1896 
   1897   EmitBranch(true_block, false_block, true_cond);
   1898 }
   1899 
   1900 
   1901 Condition LCodeGen::EmitIsString(Register input,
   1902                                  Register temp1,
   1903                                  Label* is_not_string) {
   1904   __ JumpIfSmi(input, is_not_string);
   1905   __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE);
   1906 
   1907   return lt;
   1908 }
   1909 
   1910 
   1911 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
   1912   Register reg = ToRegister(instr->InputAt(0));
   1913   Register temp1 = ToRegister(instr->TempAt(0));
   1914 
   1915   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1916   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1917   Label* false_label = chunk_->GetAssemblyLabel(false_block);
   1918 
   1919   Condition true_cond =
   1920       EmitIsString(reg, temp1, false_label);
   1921 
   1922   EmitBranch(true_block, false_block, true_cond);
   1923 }
   1924 
   1925 
   1926 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
   1927   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1928   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1929 
   1930   Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
   1931   __ tst(input_reg, Operand(kSmiTagMask));
   1932   EmitBranch(true_block, false_block, eq);
   1933 }
   1934 
   1935 
   1936 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
   1937   Register input = ToRegister(instr->InputAt(0));
   1938   Register temp = ToRegister(instr->TempAt(0));
   1939 
   1940   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1941   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1942 
   1943   __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
   1944   __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset));
   1945   __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
   1946   __ tst(temp, Operand(1 << Map::kIsUndetectable));
   1947   EmitBranch(true_block, false_block, ne);
   1948 }
   1949 
   1950 
   1951 static Condition ComputeCompareCondition(Token::Value op) {
   1952   switch (op) {
   1953     case Token::EQ_STRICT:
   1954     case Token::EQ:
   1955       return eq;
   1956     case Token::LT:
   1957       return lt;
   1958     case Token::GT:
   1959       return gt;
   1960     case Token::LTE:
   1961       return le;
   1962     case Token::GTE:
   1963       return ge;
   1964     default:
   1965       UNREACHABLE();
   1966       return kNoCondition;
   1967   }
   1968 }
   1969 
   1970 
   1971 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
   1972   Token::Value op = instr->op();
   1973   int true_block = chunk_->LookupDestination(instr->true_block_id());
   1974   int false_block = chunk_->LookupDestination(instr->false_block_id());
   1975 
   1976   Handle<Code> ic = CompareIC::GetUninitialized(op);
   1977   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   1978   __ cmp(r0, Operand(0));  // This instruction also signals no smi code inlined.
   1979 
   1980   Condition condition = ComputeCompareCondition(op);
   1981 
   1982   EmitBranch(true_block, false_block, condition);
   1983 }
   1984 
   1985 
   1986 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
   1987   InstanceType from = instr->from();
   1988   InstanceType to = instr->to();
   1989   if (from == FIRST_TYPE) return to;
   1990   ASSERT(from == to || to == LAST_TYPE);
   1991   return from;
   1992 }
   1993 
   1994 
   1995 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
   1996   InstanceType from = instr->from();
   1997   InstanceType to = instr->to();
   1998   if (from == to) return eq;
   1999   if (to == LAST_TYPE) return hs;
   2000   if (from == FIRST_TYPE) return ls;
   2001   UNREACHABLE();
   2002   return eq;
   2003 }
   2004 
   2005 
   2006 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
   2007   Register scratch = scratch0();
   2008   Register input = ToRegister(instr->InputAt(0));
   2009 
   2010   int true_block = chunk_->LookupDestination(instr->true_block_id());
   2011   int false_block = chunk_->LookupDestination(instr->false_block_id());
   2012 
   2013   Label* false_label = chunk_->GetAssemblyLabel(false_block);
   2014 
   2015   __ JumpIfSmi(input, false_label);
   2016 
   2017   __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
   2018   EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
   2019 }
   2020 
   2021 
   2022 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
   2023   Register input = ToRegister(instr->InputAt(0));
   2024   Register result = ToRegister(instr->result());
   2025 
   2026   if (FLAG_debug_code) {
   2027     __ AbortIfNotString(input);
   2028   }
   2029 
   2030   __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset));
   2031   __ IndexFromHash(result, result);
   2032 }
   2033 
   2034 
   2035 void LCodeGen::DoHasCachedArrayIndexAndBranch(
   2036     LHasCachedArrayIndexAndBranch* instr) {
   2037   Register input = ToRegister(instr->InputAt(0));
   2038   Register scratch = scratch0();
   2039 
   2040   int true_block = chunk_->LookupDestination(instr->true_block_id());
   2041   int false_block = chunk_->LookupDestination(instr->false_block_id());
   2042 
   2043   __ ldr(scratch,
   2044          FieldMemOperand(input, String::kHashFieldOffset));
   2045   __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
   2046   EmitBranch(true_block, false_block, eq);
   2047 }
   2048 
   2049 
   2050 // Branches to a label or falls through with the answer in flags.  Trashes
   2051 // the temp registers, but not the input.
   2052 void LCodeGen::EmitClassOfTest(Label* is_true,
   2053                                Label* is_false,
   2054                                Handle<String>class_name,
   2055                                Register input,
   2056                                Register temp,
   2057                                Register temp2) {
   2058   ASSERT(!input.is(temp));
   2059   ASSERT(!input.is(temp2));
   2060   ASSERT(!temp.is(temp2));
   2061 
   2062   __ JumpIfSmi(input, is_false);
   2063 
   2064   if (class_name->IsEqualTo(CStrVector("Function"))) {
   2065     // Assuming the following assertions, we can use the same compares to test
   2066     // for both being a function type and being in the object type range.
   2067     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
   2068     STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
   2069                   FIRST_SPEC_OBJECT_TYPE + 1);
   2070     STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
   2071                   LAST_SPEC_OBJECT_TYPE - 1);
   2072     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
   2073     __ CompareObjectType(input, temp, temp2, FIRST_SPEC_OBJECT_TYPE);
   2074     __ b(lt, is_false);
   2075     __ b(eq, is_true);
   2076     __ cmp(temp2, Operand(LAST_SPEC_OBJECT_TYPE));
   2077     __ b(eq, is_true);
   2078   } else {
   2079     // Faster code path to avoid two compares: subtract lower bound from the
   2080     // actual type and do a signed compare with the width of the type range.
   2081     __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset));
   2082     __ ldrb(temp2, FieldMemOperand(temp, Map::kInstanceTypeOffset));
   2083     __ sub(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
   2084     __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
   2085                           FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
   2086     __ b(gt, is_false);
   2087   }
   2088 
   2089   // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
   2090   // Check if the constructor in the map is a function.
   2091   __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset));
   2092 
   2093   // Objects with a non-function constructor have class 'Object'.
   2094   __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE);
   2095   if (class_name->IsEqualTo(CStrVector("Object"))) {
   2096     __ b(ne, is_true);
   2097   } else {
   2098     __ b(ne, is_false);
   2099   }
   2100 
   2101   // temp now contains the constructor function. Grab the
   2102   // instance class name from there.
   2103   __ ldr(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
   2104   __ ldr(temp, FieldMemOperand(temp,
   2105                                SharedFunctionInfo::kInstanceClassNameOffset));
   2106   // The class name we are testing against is a symbol because it's a literal.
   2107   // The name in the constructor is a symbol because of the way the context is
   2108   // booted.  This routine isn't expected to work for random API-created
   2109   // classes and it doesn't have to because you can't access it with natives
   2110   // syntax.  Since both sides are symbols it is sufficient to use an identity
   2111   // comparison.
   2112   __ cmp(temp, Operand(class_name));
   2113   // End with the answer in flags.
   2114 }
   2115 
   2116 
   2117 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
   2118   Register input = ToRegister(instr->InputAt(0));
   2119   Register temp = scratch0();
   2120   Register temp2 = ToRegister(instr->TempAt(0));
   2121   Handle<String> class_name = instr->hydrogen()->class_name();
   2122 
   2123   int true_block = chunk_->LookupDestination(instr->true_block_id());
   2124   int false_block = chunk_->LookupDestination(instr->false_block_id());
   2125 
   2126   Label* true_label = chunk_->GetAssemblyLabel(true_block);
   2127   Label* false_label = chunk_->GetAssemblyLabel(false_block);
   2128 
   2129   EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
   2130 
   2131   EmitBranch(true_block, false_block, eq);
   2132 }
   2133 
   2134 
   2135 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
   2136   Register reg = ToRegister(instr->InputAt(0));
   2137   Register temp = ToRegister(instr->TempAt(0));
   2138   int true_block = instr->true_block_id();
   2139   int false_block = instr->false_block_id();
   2140 
   2141   __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
   2142   __ cmp(temp, Operand(instr->map()));
   2143   EmitBranch(true_block, false_block, eq);
   2144 }
   2145 
   2146 
   2147 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
   2148   ASSERT(ToRegister(instr->InputAt(0)).is(r0));  // Object is in r0.
   2149   ASSERT(ToRegister(instr->InputAt(1)).is(r1));  // Function is in r1.
   2150 
   2151   InstanceofStub stub(InstanceofStub::kArgsInRegisters);
   2152   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   2153 
   2154   __ cmp(r0, Operand(0));
   2155   __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne);
   2156   __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq);
   2157 }
   2158 
   2159 
   2160 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
   2161   class DeferredInstanceOfKnownGlobal: public LDeferredCode {
   2162    public:
   2163     DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
   2164                                   LInstanceOfKnownGlobal* instr)
   2165         : LDeferredCode(codegen), instr_(instr) { }
   2166     virtual void Generate() {
   2167       codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
   2168     }
   2169     virtual LInstruction* instr() { return instr_; }
   2170     Label* map_check() { return &map_check_; }
   2171    private:
   2172     LInstanceOfKnownGlobal* instr_;
   2173     Label map_check_;
   2174   };
   2175 
   2176   DeferredInstanceOfKnownGlobal* deferred;
   2177   deferred = new DeferredInstanceOfKnownGlobal(this, instr);
   2178 
   2179   Label done, false_result;
   2180   Register object = ToRegister(instr->InputAt(0));
   2181   Register temp = ToRegister(instr->TempAt(0));
   2182   Register result = ToRegister(instr->result());
   2183 
   2184   ASSERT(object.is(r0));
   2185   ASSERT(result.is(r0));
   2186 
   2187   // A Smi is not instance of anything.
   2188   __ JumpIfSmi(object, &false_result);
   2189 
   2190   // This is the inlined call site instanceof cache. The two occurences of the
   2191   // hole value will be patched to the last map/result pair generated by the
   2192   // instanceof stub.
   2193   Label cache_miss;
   2194   Register map = temp;
   2195   __ ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
   2196   __ bind(deferred->map_check());  // Label for calculating code patching.
   2197   // We use Factory::the_hole_value() on purpose instead of loading from the
   2198   // root array to force relocation to be able to later patch with
   2199   // the cached map.
   2200   Handle<JSGlobalPropertyCell> cell =
   2201       factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
   2202   __ mov(ip, Operand(Handle<Object>(cell)));
   2203   __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
   2204   __ cmp(map, Operand(ip));
   2205   __ b(ne, &cache_miss);
   2206   // We use Factory::the_hole_value() on purpose instead of loading from the
   2207   // root array to force relocation to be able to later patch
   2208   // with true or false.
   2209   __ mov(result, Operand(factory()->the_hole_value()));
   2210   __ b(&done);
   2211 
   2212   // The inlined call site cache did not match. Check null and string before
   2213   // calling the deferred code.
   2214   __ bind(&cache_miss);
   2215   // Null is not instance of anything.
   2216   __ LoadRoot(ip, Heap::kNullValueRootIndex);
   2217   __ cmp(object, Operand(ip));
   2218   __ b(eq, &false_result);
   2219 
   2220   // String values is not instance of anything.
   2221   Condition is_string = masm_->IsObjectStringType(object, temp);
   2222   __ b(is_string, &false_result);
   2223 
   2224   // Go to the deferred code.
   2225   __ b(deferred->entry());
   2226 
   2227   __ bind(&false_result);
   2228   __ LoadRoot(result, Heap::kFalseValueRootIndex);
   2229 
   2230   // Here result has either true or false. Deferred code also produces true or
   2231   // false object.
   2232   __ bind(deferred->exit());
   2233   __ bind(&done);
   2234 }
   2235 
   2236 
   2237 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
   2238                                                Label* map_check) {
   2239   Register result = ToRegister(instr->result());
   2240   ASSERT(result.is(r0));
   2241 
   2242   InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
   2243   flags = static_cast<InstanceofStub::Flags>(
   2244       flags | InstanceofStub::kArgsInRegisters);
   2245   flags = static_cast<InstanceofStub::Flags>(
   2246       flags | InstanceofStub::kCallSiteInlineCheck);
   2247   flags = static_cast<InstanceofStub::Flags>(
   2248       flags | InstanceofStub::kReturnTrueFalseObject);
   2249   InstanceofStub stub(flags);
   2250 
   2251   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   2252 
   2253   // Get the temp register reserved by the instruction. This needs to be r4 as
   2254   // its slot of the pushing of safepoint registers is used to communicate the
   2255   // offset to the location of the map check.
   2256   Register temp = ToRegister(instr->TempAt(0));
   2257   ASSERT(temp.is(r4));
   2258   __ LoadHeapObject(InstanceofStub::right(), instr->function());
   2259   static const int kAdditionalDelta = 4;
   2260   int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
   2261   Label before_push_delta;
   2262   __ bind(&before_push_delta);
   2263   __ BlockConstPoolFor(kAdditionalDelta);
   2264   __ mov(temp, Operand(delta * kPointerSize));
   2265   __ StoreToSafepointRegisterSlot(temp, temp);
   2266   CallCodeGeneric(stub.GetCode(),
   2267                   RelocInfo::CODE_TARGET,
   2268                   instr,
   2269                   RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
   2270   ASSERT(instr->HasDeoptimizationEnvironment());
   2271   LEnvironment* env = instr->deoptimization_environment();
   2272   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
   2273   // Put the result value into the result register slot and
   2274   // restore all registers.
   2275   __ StoreToSafepointRegisterSlot(result, result);
   2276 }
   2277 
   2278 
   2279 void LCodeGen::DoCmpT(LCmpT* instr) {
   2280   Token::Value op = instr->op();
   2281 
   2282   Handle<Code> ic = CompareIC::GetUninitialized(op);
   2283   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   2284   __ cmp(r0, Operand(0));  // This instruction also signals no smi code inlined.
   2285 
   2286   Condition condition = ComputeCompareCondition(op);
   2287   __ LoadRoot(ToRegister(instr->result()),
   2288               Heap::kTrueValueRootIndex,
   2289               condition);
   2290   __ LoadRoot(ToRegister(instr->result()),
   2291               Heap::kFalseValueRootIndex,
   2292               NegateCondition(condition));
   2293 }
   2294 
   2295 
   2296 void LCodeGen::DoReturn(LReturn* instr) {
   2297   if (FLAG_trace) {
   2298     // Push the return value on the stack as the parameter.
   2299     // Runtime::TraceExit returns its parameter in r0.
   2300     __ push(r0);
   2301     __ CallRuntime(Runtime::kTraceExit, 1);
   2302   }
   2303   int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize;
   2304   __ mov(sp, fp);
   2305   __ ldm(ia_w, sp, fp.bit() | lr.bit());
   2306   __ add(sp, sp, Operand(sp_delta));
   2307   __ Jump(lr);
   2308 }
   2309 
   2310 
   2311 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
   2312   Register result = ToRegister(instr->result());
   2313   __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell())));
   2314   __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
   2315   if (instr->hydrogen()->RequiresHoleCheck()) {
   2316     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
   2317     __ cmp(result, ip);
   2318     DeoptimizeIf(eq, instr->environment());
   2319   }
   2320 }
   2321 
   2322 
   2323 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   2324   ASSERT(ToRegister(instr->global_object()).is(r0));
   2325   ASSERT(ToRegister(instr->result()).is(r0));
   2326 
   2327   __ mov(r2, Operand(instr->name()));
   2328   RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET
   2329                                              : RelocInfo::CODE_TARGET_CONTEXT;
   2330   Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   2331   CallCode(ic, mode, instr);
   2332 }
   2333 
   2334 
   2335 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
   2336   Register value = ToRegister(instr->value());
   2337   Register cell = scratch0();
   2338 
   2339   // Load the cell.
   2340   __ mov(cell, Operand(instr->hydrogen()->cell()));
   2341 
   2342   // If the cell we are storing to contains the hole it could have
   2343   // been deleted from the property dictionary. In that case, we need
   2344   // to update the property details in the property dictionary to mark
   2345   // it as no longer deleted.
   2346   if (instr->hydrogen()->RequiresHoleCheck()) {
   2347     // We use a temp to check the payload (CompareRoot might clobber ip).
   2348     Register payload = ToRegister(instr->TempAt(0));
   2349     __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
   2350     __ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
   2351     DeoptimizeIf(eq, instr->environment());
   2352   }
   2353 
   2354   // Store the value.
   2355   __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
   2356   // Cells are always rescanned, so no write barrier here.
   2357 }
   2358 
   2359 
   2360 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
   2361   ASSERT(ToRegister(instr->global_object()).is(r1));
   2362   ASSERT(ToRegister(instr->value()).is(r0));
   2363 
   2364   __ mov(r2, Operand(instr->name()));
   2365   Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
   2366       ? isolate()->builtins()->StoreIC_Initialize_Strict()
   2367       : isolate()->builtins()->StoreIC_Initialize();
   2368   CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
   2369 }
   2370 
   2371 
   2372 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   2373   Register context = ToRegister(instr->context());
   2374   Register result = ToRegister(instr->result());
   2375   __ ldr(result, ContextOperand(context, instr->slot_index()));
   2376   if (instr->hydrogen()->RequiresHoleCheck()) {
   2377     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
   2378     __ cmp(result, ip);
   2379     if (instr->hydrogen()->DeoptimizesOnHole()) {
   2380       DeoptimizeIf(eq, instr->environment());
   2381     } else {
   2382       __ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq);
   2383     }
   2384   }
   2385 }
   2386 
   2387 
   2388 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
   2389   Register context = ToRegister(instr->context());
   2390   Register value = ToRegister(instr->value());
   2391   Register scratch = scratch0();
   2392   MemOperand target = ContextOperand(context, instr->slot_index());
   2393 
   2394   Label skip_assignment;
   2395 
   2396   if (instr->hydrogen()->RequiresHoleCheck()) {
   2397     __ ldr(scratch, target);
   2398     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
   2399     __ cmp(scratch, ip);
   2400     if (instr->hydrogen()->DeoptimizesOnHole()) {
   2401       DeoptimizeIf(eq, instr->environment());
   2402     } else {
   2403       __ b(ne, &skip_assignment);
   2404     }
   2405   }
   2406 
   2407   __ str(value, target);
   2408   if (instr->hydrogen()->NeedsWriteBarrier()) {
   2409     HType type = instr->hydrogen()->value()->type();
   2410     SmiCheck check_needed =
   2411         type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
   2412     __ RecordWriteContextSlot(context,
   2413                               target.offset(),
   2414                               value,
   2415                               scratch,
   2416                               kLRHasBeenSaved,
   2417                               kSaveFPRegs,
   2418                               EMIT_REMEMBERED_SET,
   2419                               check_needed);
   2420   }
   2421 
   2422   __ bind(&skip_assignment);
   2423 }
   2424 
   2425 
   2426 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
   2427   Register object = ToRegister(instr->InputAt(0));
   2428   Register result = ToRegister(instr->result());
   2429   if (instr->hydrogen()->is_in_object()) {
   2430     __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset()));
   2431   } else {
   2432     __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
   2433     __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset()));
   2434   }
   2435 }
   2436 
   2437 
   2438 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
   2439                                                Register object,
   2440                                                Handle<Map> type,
   2441                                                Handle<String> name) {
   2442   LookupResult lookup(isolate());
   2443   type->LookupInDescriptors(NULL, *name, &lookup);
   2444   ASSERT(lookup.IsFound() &&
   2445          (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
   2446   if (lookup.type() == FIELD) {
   2447     int index = lookup.GetLocalFieldIndexFromMap(*type);
   2448     int offset = index * kPointerSize;
   2449     if (index < 0) {
   2450       // Negative property indices are in-object properties, indexed
   2451       // from the end of the fixed part of the object.
   2452       __ ldr(result, FieldMemOperand(object, offset + type->instance_size()));
   2453     } else {
   2454       // Non-negative property indices are in the properties array.
   2455       __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
   2456       __ ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize));
   2457     }
   2458   } else {
   2459     Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
   2460     __ LoadHeapObject(result, function);
   2461   }
   2462 }
   2463 
   2464 
   2465 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
   2466   Register object = ToRegister(instr->object());
   2467   Register result = ToRegister(instr->result());
   2468   Register scratch = scratch0();
   2469   int map_count = instr->hydrogen()->types()->length();
   2470   Handle<String> name = instr->hydrogen()->name();
   2471   if (map_count == 0) {
   2472     ASSERT(instr->hydrogen()->need_generic());
   2473     __ mov(r2, Operand(name));
   2474     Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   2475     CallCode(ic, RelocInfo::CODE_TARGET, instr);
   2476   } else {
   2477     Label done;
   2478     __ ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   2479     for (int i = 0; i < map_count - 1; ++i) {
   2480       Handle<Map> map = instr->hydrogen()->types()->at(i);
   2481       Label next;
   2482       __ cmp(scratch, Operand(map));
   2483       __ b(ne, &next);
   2484       EmitLoadFieldOrConstantFunction(result, object, map, name);
   2485       __ b(&done);
   2486       __ bind(&next);
   2487     }
   2488     Handle<Map> map = instr->hydrogen()->types()->last();
   2489     __ cmp(scratch, Operand(map));
   2490     if (instr->hydrogen()->need_generic()) {
   2491       Label generic;
   2492       __ b(ne, &generic);
   2493       EmitLoadFieldOrConstantFunction(result, object, map, name);
   2494       __ b(&done);
   2495       __ bind(&generic);
   2496       __ mov(r2, Operand(name));
   2497       Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   2498       CallCode(ic, RelocInfo::CODE_TARGET, instr);
   2499     } else {
   2500       DeoptimizeIf(ne, instr->environment());
   2501       EmitLoadFieldOrConstantFunction(result, object, map, name);
   2502     }
   2503     __ bind(&done);
   2504   }
   2505 }
   2506 
   2507 
   2508 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   2509   ASSERT(ToRegister(instr->object()).is(r0));
   2510   ASSERT(ToRegister(instr->result()).is(r0));
   2511 
   2512   // Name is always in r2.
   2513   __ mov(r2, Operand(instr->name()));
   2514   Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   2515   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   2516 }
   2517 
   2518 
   2519 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
   2520   Register scratch = scratch0();
   2521   Register function = ToRegister(instr->function());
   2522   Register result = ToRegister(instr->result());
   2523 
   2524   // Check that the function really is a function. Load map into the
   2525   // result register.
   2526   __ CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
   2527   DeoptimizeIf(ne, instr->environment());
   2528 
   2529   // Make sure that the function has an instance prototype.
   2530   Label non_instance;
   2531   __ ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
   2532   __ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
   2533   __ b(ne, &non_instance);
   2534 
   2535   // Get the prototype or initial map from the function.
   2536   __ ldr(result,
   2537          FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   2538 
   2539   // Check that the function has a prototype or an initial map.
   2540   __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
   2541   __ cmp(result, ip);
   2542   DeoptimizeIf(eq, instr->environment());
   2543 
   2544   // If the function does not have an initial map, we're done.
   2545   Label done;
   2546   __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
   2547   __ b(ne, &done);
   2548 
   2549   // Get the prototype from the initial map.
   2550   __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
   2551   __ jmp(&done);
   2552 
   2553   // Non-instance prototype: Fetch prototype from constructor field
   2554   // in initial map.
   2555   __ bind(&non_instance);
   2556   __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
   2557 
   2558   // All done.
   2559   __ bind(&done);
   2560 }
   2561 
   2562 
   2563 void LCodeGen::DoLoadElements(LLoadElements* instr) {
   2564   Register result = ToRegister(instr->result());
   2565   Register input = ToRegister(instr->InputAt(0));
   2566   Register scratch = scratch0();
   2567 
   2568   __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset));
   2569   if (FLAG_debug_code) {
   2570     Label done, fail;
   2571     __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
   2572     __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
   2573     __ cmp(scratch, ip);
   2574     __ b(eq, &done);
   2575     __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
   2576     __ cmp(scratch, ip);
   2577     __ b(eq, &done);
   2578     // |scratch| still contains |input|'s map.
   2579     __ ldr(scratch, FieldMemOperand(scratch, Map::kBitField2Offset));
   2580     __ ubfx(scratch, scratch, Map::kElementsKindShift,
   2581             Map::kElementsKindBitCount);
   2582     __ cmp(scratch, Operand(FAST_ELEMENTS));
   2583     __ b(eq, &done);
   2584     __ cmp(scratch, Operand(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND));
   2585     __ b(lt, &fail);
   2586     __ cmp(scratch, Operand(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND));
   2587     __ b(le, &done);
   2588     __ bind(&fail);
   2589     __ Abort("Check for fast or external elements failed.");
   2590     __ bind(&done);
   2591   }
   2592 }
   2593 
   2594 
   2595 void LCodeGen::DoLoadExternalArrayPointer(
   2596     LLoadExternalArrayPointer* instr) {
   2597   Register to_reg = ToRegister(instr->result());
   2598   Register from_reg  = ToRegister(instr->InputAt(0));
   2599   __ ldr(to_reg, FieldMemOperand(from_reg,
   2600                                  ExternalArray::kExternalPointerOffset));
   2601 }
   2602 
   2603 
   2604 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
   2605   Register arguments = ToRegister(instr->arguments());
   2606   Register length = ToRegister(instr->length());
   2607   Register index = ToRegister(instr->index());
   2608   Register result = ToRegister(instr->result());
   2609 
   2610   // Bailout index is not a valid argument index. Use unsigned check to get
   2611   // negative check for free.
   2612   __ sub(length, length, index, SetCC);
   2613   DeoptimizeIf(ls, instr->environment());
   2614 
   2615   // There are two words between the frame pointer and the last argument.
   2616   // Subtracting from length accounts for one of them add one more.
   2617   __ add(length, length, Operand(1));
   2618   __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2));
   2619 }
   2620 
   2621 
   2622 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
   2623   Register elements = ToRegister(instr->elements());
   2624   Register key = EmitLoadRegister(instr->key(), scratch0());
   2625   Register result = ToRegister(instr->result());
   2626   Register scratch = scratch0();
   2627 
   2628   // Load the result.
   2629   __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
   2630   __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize));
   2631 
   2632   // Check for the hole value.
   2633   if (instr->hydrogen()->RequiresHoleCheck()) {
   2634     __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
   2635     __ cmp(result, scratch);
   2636     DeoptimizeIf(eq, instr->environment());
   2637   }
   2638 }
   2639 
   2640 
   2641 void LCodeGen::DoLoadKeyedFastDoubleElement(
   2642     LLoadKeyedFastDoubleElement* instr) {
   2643   Register elements = ToRegister(instr->elements());
   2644   bool key_is_constant = instr->key()->IsConstantOperand();
   2645   Register key = no_reg;
   2646   DwVfpRegister result = ToDoubleRegister(instr->result());
   2647   Register scratch = scratch0();
   2648 
   2649   int shift_size =
   2650       ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
   2651   int constant_key = 0;
   2652   if (key_is_constant) {
   2653     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
   2654     if (constant_key & 0xF0000000) {
   2655       Abort("array index constant value too big.");
   2656     }
   2657   } else {
   2658     key = ToRegister(instr->key());
   2659   }
   2660 
   2661   Operand operand = key_is_constant
   2662       ? Operand(constant_key * (1 << shift_size) +
   2663                 FixedDoubleArray::kHeaderSize - kHeapObjectTag)
   2664       : Operand(key, LSL, shift_size);
   2665   __ add(elements, elements, operand);
   2666   if (!key_is_constant) {
   2667     __ add(elements, elements,
   2668            Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
   2669   }
   2670 
   2671   __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
   2672   __ cmp(scratch, Operand(kHoleNanUpper32));
   2673   DeoptimizeIf(eq, instr->environment());
   2674 
   2675   __ vldr(result, elements, 0);
   2676 }
   2677 
   2678 
   2679 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
   2680     LLoadKeyedSpecializedArrayElement* instr) {
   2681   Register external_pointer = ToRegister(instr->external_pointer());
   2682   Register key = no_reg;
   2683   ElementsKind elements_kind = instr->elements_kind();
   2684   bool key_is_constant = instr->key()->IsConstantOperand();
   2685   int constant_key = 0;
   2686   if (key_is_constant) {
   2687     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
   2688     if (constant_key & 0xF0000000) {
   2689       Abort("array index constant value too big.");
   2690     }
   2691   } else {
   2692     key = ToRegister(instr->key());
   2693   }
   2694   int shift_size = ElementsKindToShiftSize(elements_kind);
   2695 
   2696   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
   2697       elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
   2698     CpuFeatures::Scope scope(VFP3);
   2699     DwVfpRegister result = ToDoubleRegister(instr->result());
   2700     Operand operand = key_is_constant
   2701         ? Operand(constant_key * (1 << shift_size))
   2702         : Operand(key, LSL, shift_size);
   2703     __ add(scratch0(), external_pointer, operand);
   2704     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
   2705       __ vldr(result.low(), scratch0(), 0);
   2706       __ vcvt_f64_f32(result, result.low());
   2707     } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
   2708       __ vldr(result, scratch0(), 0);
   2709     }
   2710   } else {
   2711     Register result = ToRegister(instr->result());
   2712     MemOperand mem_operand(key_is_constant
   2713         ? MemOperand(external_pointer, constant_key * (1 << shift_size))
   2714         : MemOperand(external_pointer, key, LSL, shift_size));
   2715     switch (elements_kind) {
   2716       case EXTERNAL_BYTE_ELEMENTS:
   2717         __ ldrsb(result, mem_operand);
   2718         break;
   2719       case EXTERNAL_PIXEL_ELEMENTS:
   2720       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   2721         __ ldrb(result, mem_operand);
   2722         break;
   2723       case EXTERNAL_SHORT_ELEMENTS:
   2724         __ ldrsh(result, mem_operand);
   2725         break;
   2726       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   2727         __ ldrh(result, mem_operand);
   2728         break;
   2729       case EXTERNAL_INT_ELEMENTS:
   2730         __ ldr(result, mem_operand);
   2731         break;
   2732       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   2733         __ ldr(result, mem_operand);
   2734         __ cmp(result, Operand(0x80000000));
   2735         // TODO(danno): we could be more clever here, perhaps having a special
   2736         // version of the stub that detects if the overflow case actually
   2737         // happens, and generate code that returns a double rather than int.
   2738         DeoptimizeIf(cs, instr->environment());
   2739         break;
   2740       case EXTERNAL_FLOAT_ELEMENTS:
   2741       case EXTERNAL_DOUBLE_ELEMENTS:
   2742       case FAST_DOUBLE_ELEMENTS:
   2743       case FAST_ELEMENTS:
   2744       case FAST_SMI_ONLY_ELEMENTS:
   2745       case DICTIONARY_ELEMENTS:
   2746       case NON_STRICT_ARGUMENTS_ELEMENTS:
   2747         UNREACHABLE();
   2748         break;
   2749     }
   2750   }
   2751 }
   2752 
   2753 
   2754 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
   2755   ASSERT(ToRegister(instr->object()).is(r1));
   2756   ASSERT(ToRegister(instr->key()).is(r0));
   2757 
   2758   Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   2759   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   2760 }
   2761 
   2762 
   2763 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
   2764   Register scratch = scratch0();
   2765   Register result = ToRegister(instr->result());
   2766 
   2767   // Check if the calling frame is an arguments adaptor frame.
   2768   Label done, adapted;
   2769   __ ldr(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   2770   __ ldr(result, MemOperand(scratch, StandardFrameConstants::kContextOffset));
   2771   __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   2772 
   2773   // Result is the frame pointer for the frame if not adapted and for the real
   2774   // frame below the adaptor frame if adapted.
   2775   __ mov(result, fp, LeaveCC, ne);
   2776   __ mov(result, scratch, LeaveCC, eq);
   2777 }
   2778 
   2779 
   2780 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
   2781   Register elem = ToRegister(instr->InputAt(0));
   2782   Register result = ToRegister(instr->result());
   2783 
   2784   Label done;
   2785 
   2786   // If no arguments adaptor frame the number of arguments is fixed.
   2787   __ cmp(fp, elem);
   2788   __ mov(result, Operand(scope()->num_parameters()));
   2789   __ b(eq, &done);
   2790 
   2791   // Arguments adaptor frame present. Get argument length from there.
   2792   __ ldr(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   2793   __ ldr(result,
   2794          MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
   2795   __ SmiUntag(result);
   2796 
   2797   // Argument length is in result register.
   2798   __ bind(&done);
   2799 }
   2800 
   2801 
   2802 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
   2803   Register receiver = ToRegister(instr->receiver());
   2804   Register function = ToRegister(instr->function());
   2805   Register scratch = scratch0();
   2806 
   2807   // If the receiver is null or undefined, we have to pass the global
   2808   // object as a receiver to normal functions. Values have to be
   2809   // passed unchanged to builtins and strict-mode functions.
   2810   Label global_object, receiver_ok;
   2811 
   2812   // Do not transform the receiver to object for strict mode
   2813   // functions.
   2814   __ ldr(scratch,
   2815          FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
   2816   __ ldr(scratch,
   2817          FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
   2818   __ tst(scratch,
   2819          Operand(1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize)));
   2820   __ b(ne, &receiver_ok);
   2821 
   2822   // Do not transform the receiver to object for builtins.
   2823   __ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
   2824   __ b(ne, &receiver_ok);
   2825 
   2826   // Normal function. Replace undefined or null with global receiver.
   2827   __ LoadRoot(scratch, Heap::kNullValueRootIndex);
   2828   __ cmp(receiver, scratch);
   2829   __ b(eq, &global_object);
   2830   __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
   2831   __ cmp(receiver, scratch);
   2832   __ b(eq, &global_object);
   2833 
   2834   // Deoptimize if the receiver is not a JS object.
   2835   __ tst(receiver, Operand(kSmiTagMask));
   2836   DeoptimizeIf(eq, instr->environment());
   2837   __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
   2838   DeoptimizeIf(lt, instr->environment());
   2839   __ jmp(&receiver_ok);
   2840 
   2841   __ bind(&global_object);
   2842   __ ldr(receiver, GlobalObjectOperand());
   2843   __ ldr(receiver,
   2844          FieldMemOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
   2845   __ bind(&receiver_ok);
   2846 }
   2847 
   2848 
   2849 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
   2850   Register receiver = ToRegister(instr->receiver());
   2851   Register function = ToRegister(instr->function());
   2852   Register length = ToRegister(instr->length());
   2853   Register elements = ToRegister(instr->elements());
   2854   Register scratch = scratch0();
   2855   ASSERT(receiver.is(r0));  // Used for parameter count.
   2856   ASSERT(function.is(r1));  // Required by InvokeFunction.
   2857   ASSERT(ToRegister(instr->result()).is(r0));
   2858 
   2859   // Copy the arguments to this function possibly from the
   2860   // adaptor frame below it.
   2861   const uint32_t kArgumentsLimit = 1 * KB;
   2862   __ cmp(length, Operand(kArgumentsLimit));
   2863   DeoptimizeIf(hi, instr->environment());
   2864 
   2865   // Push the receiver and use the register to keep the original
   2866   // number of arguments.
   2867   __ push(receiver);
   2868   __ mov(receiver, length);
   2869   // The arguments are at a one pointer size offset from elements.
   2870   __ add(elements, elements, Operand(1 * kPointerSize));
   2871 
   2872   // Loop through the arguments pushing them onto the execution
   2873   // stack.
   2874   Label invoke, loop;
   2875   // length is a small non-negative integer, due to the test above.
   2876   __ cmp(length, Operand(0));
   2877   __ b(eq, &invoke);
   2878   __ bind(&loop);
   2879   __ ldr(scratch, MemOperand(elements, length, LSL, 2));
   2880   __ push(scratch);
   2881   __ sub(length, length, Operand(1), SetCC);
   2882   __ b(ne, &loop);
   2883 
   2884   __ bind(&invoke);
   2885   ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
   2886   LPointerMap* pointers = instr->pointer_map();
   2887   RecordPosition(pointers->position());
   2888   SafepointGenerator safepoint_generator(
   2889       this, pointers, Safepoint::kLazyDeopt);
   2890   // The number of arguments is stored in receiver which is r0, as expected
   2891   // by InvokeFunction.
   2892   ParameterCount actual(receiver);
   2893   __ InvokeFunction(function, actual, CALL_FUNCTION,
   2894                     safepoint_generator, CALL_AS_METHOD);
   2895   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   2896 }
   2897 
   2898 
   2899 void LCodeGen::DoPushArgument(LPushArgument* instr) {
   2900   LOperand* argument = instr->InputAt(0);
   2901   if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
   2902     Abort("DoPushArgument not implemented for double type.");
   2903   } else {
   2904     Register argument_reg = EmitLoadRegister(argument, ip);
   2905     __ push(argument_reg);
   2906   }
   2907 }
   2908 
   2909 
   2910 void LCodeGen::DoThisFunction(LThisFunction* instr) {
   2911   Register result = ToRegister(instr->result());
   2912   __ LoadHeapObject(result, instr->hydrogen()->closure());
   2913 }
   2914 
   2915 
   2916 void LCodeGen::DoContext(LContext* instr) {
   2917   Register result = ToRegister(instr->result());
   2918   __ mov(result, cp);
   2919 }
   2920 
   2921 
   2922 void LCodeGen::DoOuterContext(LOuterContext* instr) {
   2923   Register context = ToRegister(instr->context());
   2924   Register result = ToRegister(instr->result());
   2925   __ ldr(result,
   2926          MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2927 }
   2928 
   2929 
   2930 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
   2931   __ push(cp);  // The context is the first argument.
   2932   __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs());
   2933   __ push(scratch0());
   2934   __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags())));
   2935   __ push(scratch0());
   2936   CallRuntime(Runtime::kDeclareGlobals, 3, instr);
   2937 }
   2938 
   2939 
   2940 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
   2941   Register result = ToRegister(instr->result());
   2942   __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
   2943 }
   2944 
   2945 
   2946 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
   2947   Register global = ToRegister(instr->global());
   2948   Register result = ToRegister(instr->result());
   2949   __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset));
   2950 }
   2951 
   2952 
   2953 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
   2954                                  int arity,
   2955                                  LInstruction* instr,
   2956                                  CallKind call_kind) {
   2957   bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
   2958       function->shared()->formal_parameter_count() == arity;
   2959 
   2960   LPointerMap* pointers = instr->pointer_map();
   2961   RecordPosition(pointers->position());
   2962 
   2963   if (can_invoke_directly) {
   2964     __ LoadHeapObject(r1, function);
   2965     // Change context if needed.
   2966     bool change_context =
   2967         (info()->closure()->context() != function->context()) ||
   2968         scope()->contains_with() ||
   2969         (scope()->num_heap_slots() > 0);
   2970     if (change_context) {
   2971       __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
   2972     }
   2973 
   2974     // Set r0 to arguments count if adaption is not needed. Assumes that r0
   2975     // is available to write to at this point.
   2976     if (!function->NeedsArgumentsAdaption()) {
   2977       __ mov(r0, Operand(arity));
   2978     }
   2979 
   2980     // Invoke function.
   2981     __ SetCallKind(r5, call_kind);
   2982     __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
   2983     __ Call(ip);
   2984 
   2985     // Set up deoptimization.
   2986     RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
   2987   } else {
   2988     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
   2989     ParameterCount count(arity);
   2990     __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
   2991   }
   2992 
   2993   // Restore context.
   2994   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   2995 }
   2996 
   2997 
   2998 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
   2999   ASSERT(ToRegister(instr->result()).is(r0));
   3000   CallKnownFunction(instr->function(),
   3001                     instr->arity(),
   3002                     instr,
   3003                     CALL_AS_METHOD);
   3004 }
   3005 
   3006 
   3007 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
   3008   Register input = ToRegister(instr->InputAt(0));
   3009   Register result = ToRegister(instr->result());
   3010   Register scratch = scratch0();
   3011 
   3012   // Deoptimize if not a heap number.
   3013   __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
   3014   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
   3015   __ cmp(scratch, Operand(ip));
   3016   DeoptimizeIf(ne, instr->environment());
   3017 
   3018   Label done;
   3019   Register exponent = scratch0();
   3020   scratch = no_reg;
   3021   __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
   3022   // Check the sign of the argument. If the argument is positive, just
   3023   // return it.
   3024   __ tst(exponent, Operand(HeapNumber::kSignMask));
   3025   // Move the input to the result if necessary.
   3026   __ Move(result, input);
   3027   __ b(eq, &done);
   3028 
   3029   // Input is negative. Reverse its sign.
   3030   // Preserve the value of all registers.
   3031   {
   3032     PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   3033 
   3034     // Registers were saved at the safepoint, so we can use
   3035     // many scratch registers.
   3036     Register tmp1 = input.is(r1) ? r0 : r1;
   3037     Register tmp2 = input.is(r2) ? r0 : r2;
   3038     Register tmp3 = input.is(r3) ? r0 : r3;
   3039     Register tmp4 = input.is(r4) ? r0 : r4;
   3040 
   3041     // exponent: floating point exponent value.
   3042 
   3043     Label allocated, slow;
   3044     __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
   3045     __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
   3046     __ b(&allocated);
   3047 
   3048     // Slow case: Call the runtime system to do the number allocation.
   3049     __ bind(&slow);
   3050 
   3051     CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
   3052     // Set the pointer to the new heap number in tmp.
   3053     if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
   3054     // Restore input_reg after call to runtime.
   3055     __ LoadFromSafepointRegisterSlot(input, input);
   3056     __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
   3057 
   3058     __ bind(&allocated);
   3059     // exponent: floating point exponent value.
   3060     // tmp1: allocated heap number.
   3061     __ bic(exponent, exponent, Operand(HeapNumber::kSignMask));
   3062     __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
   3063     __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
   3064     __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
   3065 
   3066     __ StoreToSafepointRegisterSlot(tmp1, result);
   3067   }
   3068 
   3069   __ bind(&done);
   3070 }
   3071 
   3072 
   3073 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
   3074   Register input = ToRegister(instr->InputAt(0));
   3075   Register result = ToRegister(instr->result());
   3076   __ cmp(input, Operand(0));
   3077   __ Move(result, input, pl);
   3078   // We can make rsb conditional because the previous cmp instruction
   3079   // will clear the V (overflow) flag and rsb won't set this flag
   3080   // if input is positive.
   3081   __ rsb(result, input, Operand(0), SetCC, mi);
   3082   // Deoptimize on overflow.
   3083   DeoptimizeIf(vs, instr->environment());
   3084 }
   3085 
   3086 
   3087 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
   3088   // Class for deferred case.
   3089   class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
   3090    public:
   3091     DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
   3092                                     LUnaryMathOperation* instr)
   3093         : LDeferredCode(codegen), instr_(instr) { }
   3094     virtual void Generate() {
   3095       codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
   3096     }
   3097     virtual LInstruction* instr() { return instr_; }
   3098    private:
   3099     LUnaryMathOperation* instr_;
   3100   };
   3101 
   3102   Representation r = instr->hydrogen()->value()->representation();
   3103   if (r.IsDouble()) {
   3104     DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
   3105     DwVfpRegister result = ToDoubleRegister(instr->result());
   3106     __ vabs(result, input);
   3107   } else if (r.IsInteger32()) {
   3108     EmitIntegerMathAbs(instr);
   3109   } else {
   3110     // Representation is tagged.
   3111     DeferredMathAbsTaggedHeapNumber* deferred =
   3112         new DeferredMathAbsTaggedHeapNumber(this, instr);
   3113     Register input = ToRegister(instr->InputAt(0));
   3114     // Smi check.
   3115     __ JumpIfNotSmi(input, deferred->entry());
   3116     // If smi, handle it directly.
   3117     EmitIntegerMathAbs(instr);
   3118     __ bind(deferred->exit());
   3119   }
   3120 }
   3121 
   3122 
   3123 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
   3124   DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
   3125   Register result = ToRegister(instr->result());
   3126   SwVfpRegister single_scratch = double_scratch0().low();
   3127   Register scratch1 = scratch0();
   3128   Register scratch2 = ToRegister(instr->TempAt(0));
   3129 
   3130   __ EmitVFPTruncate(kRoundToMinusInf,
   3131                      single_scratch,
   3132                      input,
   3133                      scratch1,
   3134                      scratch2);
   3135   DeoptimizeIf(ne, instr->environment());
   3136 
   3137   // Move the result back to general purpose register r0.
   3138   __ vmov(result, single_scratch);
   3139 
   3140   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
   3141     // Test for -0.
   3142     Label done;
   3143     __ cmp(result, Operand(0));
   3144     __ b(ne, &done);
   3145     __ vmov(scratch1, input.high());
   3146     __ tst(scratch1, Operand(HeapNumber::kSignMask));
   3147     DeoptimizeIf(ne, instr->environment());
   3148     __ bind(&done);
   3149   }
   3150 }
   3151 
   3152 
   3153 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
   3154   DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
   3155   Register result = ToRegister(instr->result());
   3156   Register scratch = scratch0();
   3157   Label done, check_sign_on_zero;
   3158 
   3159   // Extract exponent bits.
   3160   __ vmov(result, input.high());
   3161   __ ubfx(scratch,
   3162           result,
   3163           HeapNumber::kExponentShift,
   3164           HeapNumber::kExponentBits);
   3165 
   3166   // If the number is in ]-0.5, +0.5[, the result is +/- 0.
   3167   __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2));
   3168   __ mov(result, Operand(0), LeaveCC, le);
   3169   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
   3170     __ b(le, &check_sign_on_zero);
   3171   } else {
   3172     __ b(le, &done);
   3173   }
   3174 
   3175   // The following conversion will not work with numbers
   3176   // outside of ]-2^32, 2^32[.
   3177   __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32));
   3178   DeoptimizeIf(ge, instr->environment());
   3179 
   3180   // Save the original sign for later comparison.
   3181   __ and_(scratch, result, Operand(HeapNumber::kSignMask));
   3182 
   3183   __ Vmov(double_scratch0(), 0.5);
   3184   __ vadd(double_scratch0(), input, double_scratch0());
   3185 
   3186   // Check sign of the result: if the sign changed, the input
   3187   // value was in ]0.5, 0[ and the result should be -0.
   3188   __ vmov(result, double_scratch0().high());
   3189   __ eor(result, result, Operand(scratch), SetCC);
   3190   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
   3191     DeoptimizeIf(mi, instr->environment());
   3192   } else {
   3193     __ mov(result, Operand(0), LeaveCC, mi);
   3194     __ b(mi, &done);
   3195   }
   3196 
   3197   __ EmitVFPTruncate(kRoundToMinusInf,
   3198                      double_scratch0().low(),
   3199                      double_scratch0(),
   3200                      result,
   3201                      scratch);
   3202   DeoptimizeIf(ne, instr->environment());
   3203   __ vmov(result, double_scratch0().low());
   3204 
   3205   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
   3206     // Test for -0.
   3207     __ cmp(result, Operand(0));
   3208     __ b(ne, &done);
   3209     __ bind(&check_sign_on_zero);
   3210     __ vmov(scratch, input.high());
   3211     __ tst(scratch, Operand(HeapNumber::kSignMask));
   3212     DeoptimizeIf(ne, instr->environment());
   3213   }
   3214   __ bind(&done);
   3215 }
   3216 
   3217 
   3218 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
   3219   DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
   3220   DoubleRegister result = ToDoubleRegister(instr->result());
   3221   __ vsqrt(result, input);
   3222 }
   3223 
   3224 
   3225 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
   3226   DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
   3227   DoubleRegister result = ToDoubleRegister(instr->result());
   3228   DoubleRegister temp = ToDoubleRegister(instr->TempAt(0));
   3229 
   3230   // Note that according to ECMA-262 15.8.2.13:
   3231   // Math.pow(-Infinity, 0.5) == Infinity
   3232   // Math.sqrt(-Infinity) == NaN
   3233   Label done;
   3234   __ vmov(temp, -V8_INFINITY);
   3235   __ VFPCompareAndSetFlags(input, temp);
   3236   __ vneg(result, temp, eq);
   3237   __ b(&done, eq);
   3238 
   3239   // Add +0 to convert -0 to +0.
   3240   __ vadd(result, input, kDoubleRegZero);
   3241   __ vsqrt(result, result);
   3242   __ bind(&done);
   3243 }
   3244 
   3245 
   3246 void LCodeGen::DoPower(LPower* instr) {
   3247   Representation exponent_type = instr->hydrogen()->right()->representation();
   3248   // Having marked this as a call, we can use any registers.
   3249   // Just make sure that the input/output registers are the expected ones.
   3250   ASSERT(!instr->InputAt(1)->IsDoubleRegister() ||
   3251          ToDoubleRegister(instr->InputAt(1)).is(d2));
   3252   ASSERT(!instr->InputAt(1)->IsRegister() ||
   3253          ToRegister(instr->InputAt(1)).is(r2));
   3254   ASSERT(ToDoubleRegister(instr->InputAt(0)).is(d1));
   3255   ASSERT(ToDoubleRegister(instr->result()).is(d3));
   3256 
   3257   if (exponent_type.IsTagged()) {
   3258     Label no_deopt;
   3259     __ JumpIfSmi(r2, &no_deopt);
   3260     __ ldr(r7, FieldMemOperand(r2, HeapObject::kMapOffset));
   3261     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
   3262     __ cmp(r7, Operand(ip));
   3263     DeoptimizeIf(ne, instr->environment());
   3264     __ bind(&no_deopt);
   3265     MathPowStub stub(MathPowStub::TAGGED);
   3266     __ CallStub(&stub);
   3267   } else if (exponent_type.IsInteger32()) {
   3268     MathPowStub stub(MathPowStub::INTEGER);
   3269     __ CallStub(&stub);
   3270   } else {
   3271     ASSERT(exponent_type.IsDouble());
   3272     MathPowStub stub(MathPowStub::DOUBLE);
   3273     __ CallStub(&stub);
   3274   }
   3275 }
   3276 
   3277 
   3278 void LCodeGen::DoRandom(LRandom* instr) {
   3279   class DeferredDoRandom: public LDeferredCode {
   3280    public:
   3281     DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
   3282         : LDeferredCode(codegen), instr_(instr) { }
   3283     virtual void Generate() { codegen()->DoDeferredRandom(instr_); }
   3284     virtual LInstruction* instr() { return instr_; }
   3285    private:
   3286     LRandom* instr_;
   3287   };
   3288 
   3289   DeferredDoRandom* deferred = new DeferredDoRandom(this, instr);
   3290 
   3291   // Having marked this instruction as a call we can use any
   3292   // registers.
   3293   ASSERT(ToDoubleRegister(instr->result()).is(d7));
   3294   ASSERT(ToRegister(instr->InputAt(0)).is(r0));
   3295 
   3296   static const int kSeedSize = sizeof(uint32_t);
   3297   STATIC_ASSERT(kPointerSize == kSeedSize);
   3298 
   3299   __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
   3300   static const int kRandomSeedOffset =
   3301       FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
   3302   __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset));
   3303   // r2: FixedArray of the global context's random seeds
   3304 
   3305   // Load state[0].
   3306   __ ldr(r1, FieldMemOperand(r2, ByteArray::kHeaderSize));
   3307   __ cmp(r1, Operand(0));
   3308   __ b(eq, deferred->entry());
   3309   // Load state[1].
   3310   __ ldr(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize));
   3311   // r1: state[0].
   3312   // r0: state[1].
   3313 
   3314   // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
   3315   __ and_(r3, r1, Operand(0xFFFF));
   3316   __ mov(r4, Operand(18273));
   3317   __ mul(r3, r3, r4);
   3318   __ add(r1, r3, Operand(r1, LSR, 16));
   3319   // Save state[0].
   3320   __ str(r1, FieldMemOperand(r2, ByteArray::kHeaderSize));
   3321 
   3322   // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
   3323   __ and_(r3, r0, Operand(0xFFFF));
   3324   __ mov(r4, Operand(36969));
   3325   __ mul(r3, r3, r4);
   3326   __ add(r0, r3, Operand(r0, LSR, 16));
   3327   // Save state[1].
   3328   __ str(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize));
   3329 
   3330   // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
   3331   __ and_(r0, r0, Operand(0x3FFFF));
   3332   __ add(r0, r0, Operand(r1, LSL, 14));
   3333 
   3334   __ bind(deferred->exit());
   3335   // 0x41300000 is the top half of 1.0 x 2^20 as a double.
   3336   // Create this constant using mov/orr to avoid PC relative load.
   3337   __ mov(r1, Operand(0x41000000));
   3338   __ orr(r1, r1, Operand(0x300000));
   3339   // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
   3340   __ vmov(d7, r0, r1);
   3341   // Move 0x4130000000000000 to VFP.
   3342   __ mov(r0, Operand(0, RelocInfo::NONE));
   3343   __ vmov(d8, r0, r1);
   3344   // Subtract and store the result in the heap number.
   3345   __ vsub(d7, d7, d8);
   3346 }
   3347 
   3348 
   3349 void LCodeGen::DoDeferredRandom(LRandom* instr) {
   3350   __ PrepareCallCFunction(1, scratch0());
   3351   __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
   3352   // Return value is in r0.
   3353 }
   3354 
   3355 
   3356 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
   3357   ASSERT(ToDoubleRegister(instr->result()).is(d2));
   3358   TranscendentalCacheStub stub(TranscendentalCache::LOG,
   3359                                TranscendentalCacheStub::UNTAGGED);
   3360   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   3361 }
   3362 
   3363 
   3364 void LCodeGen::DoMathTan(LUnaryMathOperation* instr) {
   3365   ASSERT(ToDoubleRegister(instr->result()).is(d2));
   3366   TranscendentalCacheStub stub(TranscendentalCache::TAN,
   3367                                TranscendentalCacheStub::UNTAGGED);
   3368   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   3369 }
   3370 
   3371 
   3372 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
   3373   ASSERT(ToDoubleRegister(instr->result()).is(d2));
   3374   TranscendentalCacheStub stub(TranscendentalCache::COS,
   3375                                TranscendentalCacheStub::UNTAGGED);
   3376   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   3377 }
   3378 
   3379 
   3380 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
   3381   ASSERT(ToDoubleRegister(instr->result()).is(d2));
   3382   TranscendentalCacheStub stub(TranscendentalCache::SIN,
   3383                                TranscendentalCacheStub::UNTAGGED);
   3384   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   3385 }
   3386 
   3387 
   3388 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
   3389   switch (instr->op()) {
   3390     case kMathAbs:
   3391       DoMathAbs(instr);
   3392       break;
   3393     case kMathFloor:
   3394       DoMathFloor(instr);
   3395       break;
   3396     case kMathRound:
   3397       DoMathRound(instr);
   3398       break;
   3399     case kMathSqrt:
   3400       DoMathSqrt(instr);
   3401       break;
   3402     case kMathPowHalf:
   3403       DoMathPowHalf(instr);
   3404       break;
   3405     case kMathCos:
   3406       DoMathCos(instr);
   3407       break;
   3408     case kMathSin:
   3409       DoMathSin(instr);
   3410       break;
   3411     case kMathTan:
   3412       DoMathTan(instr);
   3413       break;
   3414     case kMathLog:
   3415       DoMathLog(instr);
   3416       break;
   3417     default:
   3418       Abort("Unimplemented type of LUnaryMathOperation.");
   3419       UNREACHABLE();
   3420   }
   3421 }
   3422 
   3423 
   3424 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
   3425   ASSERT(ToRegister(instr->function()).is(r1));
   3426   ASSERT(instr->HasPointerMap());
   3427   ASSERT(instr->HasDeoptimizationEnvironment());
   3428   LPointerMap* pointers = instr->pointer_map();
   3429   RecordPosition(pointers->position());
   3430   SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
   3431   ParameterCount count(instr->arity());
   3432   __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
   3433   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   3434 }
   3435 
   3436 
   3437 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
   3438   ASSERT(ToRegister(instr->result()).is(r0));
   3439 
   3440   int arity = instr->arity();
   3441   Handle<Code> ic =
   3442       isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
   3443   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   3444   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   3445 }
   3446 
   3447 
   3448 void LCodeGen::DoCallNamed(LCallNamed* instr) {
   3449   ASSERT(ToRegister(instr->result()).is(r0));
   3450 
   3451   int arity = instr->arity();
   3452   RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
   3453   Handle<Code> ic =
   3454       isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
   3455   __ mov(r2, Operand(instr->name()));
   3456   CallCode(ic, mode, instr);
   3457   // Restore context register.
   3458   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   3459 }
   3460 
   3461 
   3462 void LCodeGen::DoCallFunction(LCallFunction* instr) {
   3463   ASSERT(ToRegister(instr->function()).is(r1));
   3464   ASSERT(ToRegister(instr->result()).is(r0));
   3465 
   3466   int arity = instr->arity();
   3467   CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
   3468   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   3469   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   3470 }
   3471 
   3472 
   3473 void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
   3474   ASSERT(ToRegister(instr->result()).is(r0));
   3475 
   3476   int arity = instr->arity();
   3477   RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
   3478   Handle<Code> ic =
   3479       isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
   3480   __ mov(r2, Operand(instr->name()));
   3481   CallCode(ic, mode, instr);
   3482   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   3483 }
   3484 
   3485 
   3486 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
   3487   ASSERT(ToRegister(instr->result()).is(r0));
   3488   CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
   3489 }
   3490 
   3491 
   3492 void LCodeGen::DoCallNew(LCallNew* instr) {
   3493   ASSERT(ToRegister(instr->InputAt(0)).is(r1));
   3494   ASSERT(ToRegister(instr->result()).is(r0));
   3495 
   3496   CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
   3497   __ mov(r0, Operand(instr->arity()));
   3498   CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
   3499 }
   3500 
   3501 
   3502 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
   3503   CallRuntime(instr->function(), instr->arity(), instr);
   3504 }
   3505 
   3506 
   3507 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   3508   Register object = ToRegister(instr->object());
   3509   Register value = ToRegister(instr->value());
   3510   Register scratch = scratch0();
   3511   int offset = instr->offset();
   3512 
   3513   ASSERT(!object.is(value));
   3514 
   3515   if (!instr->transition().is_null()) {
   3516     __ mov(scratch, Operand(instr->transition()));
   3517     __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   3518   }
   3519 
   3520   // Do the store.
   3521   HType type = instr->hydrogen()->value()->type();
   3522   SmiCheck check_needed =
   3523       type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
   3524   if (instr->is_in_object()) {
   3525     __ str(value, FieldMemOperand(object, offset));
   3526     if (instr->hydrogen()->NeedsWriteBarrier()) {
   3527       // Update the write barrier for the object for in-object properties.
   3528       __ RecordWriteField(object,
   3529                           offset,
   3530                           value,
   3531                           scratch,
   3532                           kLRHasBeenSaved,
   3533                           kSaveFPRegs,
   3534                           EMIT_REMEMBERED_SET,
   3535                           check_needed);
   3536     }
   3537   } else {
   3538     __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
   3539     __ str(value, FieldMemOperand(scratch, offset));
   3540     if (instr->hydrogen()->NeedsWriteBarrier()) {
   3541       // Update the write barrier for the properties array.
   3542       // object is used as a scratch register.
   3543       __ RecordWriteField(scratch,
   3544                           offset,
   3545                           value,
   3546                           object,
   3547                           kLRHasBeenSaved,
   3548                           kSaveFPRegs,
   3549                           EMIT_REMEMBERED_SET,
   3550                           check_needed);
   3551     }
   3552   }
   3553 }
   3554 
   3555 
   3556 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   3557   ASSERT(ToRegister(instr->object()).is(r1));
   3558   ASSERT(ToRegister(instr->value()).is(r0));
   3559 
   3560   // Name is always in r2.
   3561   __ mov(r2, Operand(instr->name()));
   3562   Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
   3563       ? isolate()->builtins()->StoreIC_Initialize_Strict()
   3564       : isolate()->builtins()->StoreIC_Initialize();
   3565   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   3566 }
   3567 
   3568 
   3569 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
   3570   __ cmp(ToRegister(instr->index()), ToRegister(instr->length()));
   3571   DeoptimizeIf(hs, instr->environment());
   3572 }
   3573 
   3574 
   3575 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
   3576   Register value = ToRegister(instr->value());
   3577   Register elements = ToRegister(instr->object());
   3578   Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
   3579   Register scratch = scratch0();
   3580 
   3581   // Do the store.
   3582   if (instr->key()->IsConstantOperand()) {
   3583     ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
   3584     LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
   3585     int offset =
   3586         ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
   3587     __ str(value, FieldMemOperand(elements, offset));
   3588   } else {
   3589     __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
   3590     __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize));
   3591   }
   3592 
   3593   if (instr->hydrogen()->NeedsWriteBarrier()) {
   3594     HType type = instr->hydrogen()->value()->type();
   3595     SmiCheck check_needed =
   3596         type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
   3597     // Compute address of modified element and store it into key register.
   3598     __ add(key, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   3599     __ RecordWrite(elements,
   3600                    key,
   3601                    value,
   3602                    kLRHasBeenSaved,
   3603                    kSaveFPRegs,
   3604                    EMIT_REMEMBERED_SET,
   3605                    check_needed);
   3606   }
   3607 }
   3608 
   3609 
   3610 void LCodeGen::DoStoreKeyedFastDoubleElement(
   3611     LStoreKeyedFastDoubleElement* instr) {
   3612   DwVfpRegister value = ToDoubleRegister(instr->value());
   3613   Register elements = ToRegister(instr->elements());
   3614   Register key = no_reg;
   3615   Register scratch = scratch0();
   3616   bool key_is_constant = instr->key()->IsConstantOperand();
   3617   int constant_key = 0;
   3618   Label not_nan;
   3619 
   3620   // Calculate the effective address of the slot in the array to store the
   3621   // double value.
   3622   if (key_is_constant) {
   3623     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
   3624     if (constant_key & 0xF0000000) {
   3625       Abort("array index constant value too big.");
   3626     }
   3627   } else {
   3628     key = ToRegister(instr->key());
   3629   }
   3630   int shift_size = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
   3631   Operand operand = key_is_constant
   3632       ? Operand(constant_key * (1 << shift_size) +
   3633                 FixedDoubleArray::kHeaderSize - kHeapObjectTag)
   3634       : Operand(key, LSL, shift_size);
   3635   __ add(scratch, elements, operand);
   3636   if (!key_is_constant) {
   3637     __ add(scratch, scratch,
   3638            Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
   3639   }
   3640 
   3641   // Check for NaN. All NaNs must be canonicalized.
   3642   __ VFPCompareAndSetFlags(value, value);
   3643 
   3644   // Only load canonical NaN if the comparison above set the overflow.
   3645   __ Vmov(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double(), vs);
   3646 
   3647   __ bind(&not_nan);
   3648   __ vstr(value, scratch, 0);
   3649 }
   3650 
   3651 
   3652 void LCodeGen::DoStoreKeyedSpecializedArrayElement(
   3653     LStoreKeyedSpecializedArrayElement* instr) {
   3654 
   3655   Register external_pointer = ToRegister(instr->external_pointer());
   3656   Register key = no_reg;
   3657   ElementsKind elements_kind = instr->elements_kind();
   3658   bool key_is_constant = instr->key()->IsConstantOperand();
   3659   int constant_key = 0;
   3660   if (key_is_constant) {
   3661     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
   3662     if (constant_key & 0xF0000000) {
   3663       Abort("array index constant value too big.");
   3664     }
   3665   } else {
   3666     key = ToRegister(instr->key());
   3667   }
   3668   int shift_size = ElementsKindToShiftSize(elements_kind);
   3669 
   3670   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
   3671       elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
   3672     CpuFeatures::Scope scope(VFP3);
   3673     DwVfpRegister value(ToDoubleRegister(instr->value()));
   3674     Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
   3675                                     : Operand(key, LSL, shift_size));
   3676     __ add(scratch0(), external_pointer, operand);
   3677     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
   3678       __ vcvt_f32_f64(double_scratch0().low(), value);
   3679       __ vstr(double_scratch0().low(), scratch0(), 0);
   3680     } else {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
   3681       __ vstr(value, scratch0(), 0);
   3682     }
   3683   } else {
   3684     Register value(ToRegister(instr->value()));
   3685     MemOperand mem_operand(key_is_constant
   3686         ? MemOperand(external_pointer, constant_key * (1 << shift_size))
   3687         : MemOperand(external_pointer, key, LSL, shift_size));
   3688     switch (elements_kind) {
   3689       case EXTERNAL_PIXEL_ELEMENTS:
   3690       case EXTERNAL_BYTE_ELEMENTS:
   3691       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   3692         __ strb(value, mem_operand);
   3693         break;
   3694       case EXTERNAL_SHORT_ELEMENTS:
   3695       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   3696         __ strh(value, mem_operand);
   3697         break;
   3698       case EXTERNAL_INT_ELEMENTS:
   3699       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   3700         __ str(value, mem_operand);
   3701         break;
   3702       case EXTERNAL_FLOAT_ELEMENTS:
   3703       case EXTERNAL_DOUBLE_ELEMENTS:
   3704       case FAST_DOUBLE_ELEMENTS:
   3705       case FAST_ELEMENTS:
   3706       case FAST_SMI_ONLY_ELEMENTS:
   3707       case DICTIONARY_ELEMENTS:
   3708       case NON_STRICT_ARGUMENTS_ELEMENTS:
   3709         UNREACHABLE();
   3710         break;
   3711     }
   3712   }
   3713 }
   3714 
   3715 
   3716 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   3717   ASSERT(ToRegister(instr->object()).is(r2));
   3718   ASSERT(ToRegister(instr->key()).is(r1));
   3719   ASSERT(ToRegister(instr->value()).is(r0));
   3720 
   3721   Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
   3722       ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
   3723       : isolate()->builtins()->KeyedStoreIC_Initialize();
   3724   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   3725 }
   3726 
   3727 
   3728 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
   3729   Register object_reg = ToRegister(instr->object());
   3730   Register new_map_reg = ToRegister(instr->new_map_reg());
   3731   Register scratch = scratch0();
   3732 
   3733   Handle<Map> from_map = instr->original_map();
   3734   Handle<Map> to_map = instr->transitioned_map();
   3735   ElementsKind from_kind = from_map->elements_kind();
   3736   ElementsKind to_kind = to_map->elements_kind();
   3737 
   3738   Label not_applicable;
   3739   __ ldr(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
   3740   __ cmp(scratch, Operand(from_map));
   3741   __ b(ne, &not_applicable);
   3742   __ mov(new_map_reg, Operand(to_map));
   3743   if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) {
   3744     __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
   3745     // Write barrier.
   3746     __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
   3747                         scratch, kLRHasBeenSaved, kDontSaveFPRegs);
   3748   } else if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
   3749       to_kind == FAST_DOUBLE_ELEMENTS) {
   3750     Register fixed_object_reg = ToRegister(instr->temp_reg());
   3751     ASSERT(fixed_object_reg.is(r2));
   3752     ASSERT(new_map_reg.is(r3));
   3753     __ mov(fixed_object_reg, object_reg);
   3754     CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
   3755              RelocInfo::CODE_TARGET, instr);
   3756   } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
   3757     Register fixed_object_reg = ToRegister(instr->temp_reg());
   3758     ASSERT(fixed_object_reg.is(r2));
   3759     ASSERT(new_map_reg.is(r3));
   3760     __ mov(fixed_object_reg, object_reg);
   3761     CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
   3762              RelocInfo::CODE_TARGET, instr);
   3763   } else {
   3764     UNREACHABLE();
   3765   }
   3766   __ bind(&not_applicable);
   3767 }
   3768 
   3769 
   3770 void LCodeGen::DoStringAdd(LStringAdd* instr) {
   3771   __ push(ToRegister(instr->left()));
   3772   __ push(ToRegister(instr->right()));
   3773   StringAddStub stub(NO_STRING_CHECK_IN_STUB);
   3774   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   3775 }
   3776 
   3777 
   3778 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
   3779   class DeferredStringCharCodeAt: public LDeferredCode {
   3780    public:
   3781     DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
   3782         : LDeferredCode(codegen), instr_(instr) { }
   3783     virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
   3784     virtual LInstruction* instr() { return instr_; }
   3785    private:
   3786     LStringCharCodeAt* instr_;
   3787   };
   3788 
   3789   DeferredStringCharCodeAt* deferred =
   3790       new DeferredStringCharCodeAt(this, instr);
   3791 
   3792   StringCharLoadGenerator::Generate(masm(),
   3793                                     ToRegister(instr->string()),
   3794                                     ToRegister(instr->index()),
   3795                                     ToRegister(instr->result()),
   3796                                     deferred->entry());
   3797   __ bind(deferred->exit());
   3798 }
   3799 
   3800 
   3801 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
   3802   Register string = ToRegister(instr->string());
   3803   Register result = ToRegister(instr->result());
   3804   Register scratch = scratch0();
   3805 
   3806   // TODO(3095996): Get rid of this. For now, we need to make the
   3807   // result register contain a valid pointer because it is already
   3808   // contained in the register pointer map.
   3809   __ mov(result, Operand(0));
   3810 
   3811   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   3812   __ push(string);
   3813   // Push the index as a smi. This is safe because of the checks in
   3814   // DoStringCharCodeAt above.
   3815   if (instr->index()->IsConstantOperand()) {
   3816     int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
   3817     __ mov(scratch, Operand(Smi::FromInt(const_index)));
   3818     __ push(scratch);
   3819   } else {
   3820     Register index = ToRegister(instr->index());
   3821     __ SmiTag(index);
   3822     __ push(index);
   3823   }
   3824   CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr);
   3825   if (FLAG_debug_code) {
   3826     __ AbortIfNotSmi(r0);
   3827   }
   3828   __ SmiUntag(r0);
   3829   __ StoreToSafepointRegisterSlot(r0, result);
   3830 }
   3831 
   3832 
   3833 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
   3834   class DeferredStringCharFromCode: public LDeferredCode {
   3835    public:
   3836     DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
   3837         : LDeferredCode(codegen), instr_(instr) { }
   3838     virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
   3839     virtual LInstruction* instr() { return instr_; }
   3840    private:
   3841     LStringCharFromCode* instr_;
   3842   };
   3843 
   3844   DeferredStringCharFromCode* deferred =
   3845       new DeferredStringCharFromCode(this, instr);
   3846 
   3847   ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
   3848   Register char_code = ToRegister(instr->char_code());
   3849   Register result = ToRegister(instr->result());
   3850   ASSERT(!char_code.is(result));
   3851 
   3852   __ cmp(char_code, Operand(String::kMaxAsciiCharCode));
   3853   __ b(hi, deferred->entry());
   3854   __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
   3855   __ add(result, result, Operand(char_code, LSL, kPointerSizeLog2));
   3856   __ ldr(result, FieldMemOperand(result, FixedArray::kHeaderSize));
   3857   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   3858   __ cmp(result, ip);
   3859   __ b(eq, deferred->entry());
   3860   __ bind(deferred->exit());
   3861 }
   3862 
   3863 
   3864 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
   3865   Register char_code = ToRegister(instr->char_code());
   3866   Register result = ToRegister(instr->result());
   3867 
   3868   // TODO(3095996): Get rid of this. For now, we need to make the
   3869   // result register contain a valid pointer because it is already
   3870   // contained in the register pointer map.
   3871   __ mov(result, Operand(0));
   3872 
   3873   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   3874   __ SmiTag(char_code);
   3875   __ push(char_code);
   3876   CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr);
   3877   __ StoreToSafepointRegisterSlot(r0, result);
   3878 }
   3879 
   3880 
   3881 void LCodeGen::DoStringLength(LStringLength* instr) {
   3882   Register string = ToRegister(instr->InputAt(0));
   3883   Register result = ToRegister(instr->result());
   3884   __ ldr(result, FieldMemOperand(string, String::kLengthOffset));
   3885 }
   3886 
   3887 
   3888 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
   3889   LOperand* input = instr->InputAt(0);
   3890   ASSERT(input->IsRegister() || input->IsStackSlot());
   3891   LOperand* output = instr->result();
   3892   ASSERT(output->IsDoubleRegister());
   3893   SwVfpRegister single_scratch = double_scratch0().low();
   3894   if (input->IsStackSlot()) {
   3895     Register scratch = scratch0();
   3896     __ ldr(scratch, ToMemOperand(input));
   3897     __ vmov(single_scratch, scratch);
   3898   } else {
   3899     __ vmov(single_scratch, ToRegister(input));
   3900   }
   3901   __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch);
   3902 }
   3903 
   3904 
   3905 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
   3906   class DeferredNumberTagI: public LDeferredCode {
   3907    public:
   3908     DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
   3909         : LDeferredCode(codegen), instr_(instr) { }
   3910     virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); }
   3911     virtual LInstruction* instr() { return instr_; }
   3912    private:
   3913     LNumberTagI* instr_;
   3914   };
   3915 
   3916   Register src = ToRegister(instr->InputAt(0));
   3917   Register dst = ToRegister(instr->result());
   3918 
   3919   DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr);
   3920   __ SmiTag(dst, src, SetCC);
   3921   __ b(vs, deferred->entry());
   3922   __ bind(deferred->exit());
   3923 }
   3924 
   3925 
   3926 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
   3927   Label slow;
   3928   Register src = ToRegister(instr->InputAt(0));
   3929   Register dst = ToRegister(instr->result());
   3930   DoubleRegister dbl_scratch = double_scratch0();
   3931   SwVfpRegister flt_scratch = dbl_scratch.low();
   3932 
   3933   // Preserve the value of all registers.
   3934   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   3935 
   3936   // There was overflow, so bits 30 and 31 of the original integer
   3937   // disagree. Try to allocate a heap number in new space and store
   3938   // the value in there. If that fails, call the runtime system.
   3939   Label done;
   3940   if (dst.is(src)) {
   3941     __ SmiUntag(src, dst);
   3942     __ eor(src, src, Operand(0x80000000));
   3943   }
   3944   __ vmov(flt_scratch, src);
   3945   __ vcvt_f64_s32(dbl_scratch, flt_scratch);
   3946   if (FLAG_inline_new) {
   3947     __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
   3948     __ AllocateHeapNumber(r5, r3, r4, r6, &slow);
   3949     __ Move(dst, r5);
   3950     __ b(&done);
   3951   }
   3952 
   3953   // Slow case: Call the runtime system to do the number allocation.
   3954   __ bind(&slow);
   3955 
   3956   // TODO(3095996): Put a valid pointer value in the stack slot where the result
   3957   // register is stored, as this register is in the pointer map, but contains an
   3958   // integer value.
   3959   __ mov(ip, Operand(0));
   3960   __ StoreToSafepointRegisterSlot(ip, dst);
   3961   CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
   3962   __ Move(dst, r0);
   3963 
   3964   // Done. Put the value in dbl_scratch into the value of the allocated heap
   3965   // number.
   3966   __ bind(&done);
   3967   __ sub(ip, dst, Operand(kHeapObjectTag));
   3968   __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset);
   3969   __ StoreToSafepointRegisterSlot(dst, dst);
   3970 }
   3971 
   3972 
   3973 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
   3974   class DeferredNumberTagD: public LDeferredCode {
   3975    public:
   3976     DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
   3977         : LDeferredCode(codegen), instr_(instr) { }
   3978     virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
   3979     virtual LInstruction* instr() { return instr_; }
   3980    private:
   3981     LNumberTagD* instr_;
   3982   };
   3983 
   3984   DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0));
   3985   Register scratch = scratch0();
   3986   Register reg = ToRegister(instr->result());
   3987   Register temp1 = ToRegister(instr->TempAt(0));
   3988   Register temp2 = ToRegister(instr->TempAt(1));
   3989 
   3990   DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
   3991   if (FLAG_inline_new) {
   3992     __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
   3993     __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
   3994   } else {
   3995     __ jmp(deferred->entry());
   3996   }
   3997   __ bind(deferred->exit());
   3998   __ sub(ip, reg, Operand(kHeapObjectTag));
   3999   __ vstr(input_reg, ip, HeapNumber::kValueOffset);
   4000 }
   4001 
   4002 
   4003 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
   4004   // TODO(3095996): Get rid of this. For now, we need to make the
   4005   // result register contain a valid pointer because it is already
   4006   // contained in the register pointer map.
   4007   Register reg = ToRegister(instr->result());
   4008   __ mov(reg, Operand(0));
   4009 
   4010   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   4011   CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
   4012   __ StoreToSafepointRegisterSlot(r0, reg);
   4013 }
   4014 
   4015 
   4016 void LCodeGen::DoSmiTag(LSmiTag* instr) {
   4017   ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
   4018   __ SmiTag(ToRegister(instr->result()), ToRegister(instr->InputAt(0)));
   4019 }
   4020 
   4021 
   4022 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
   4023   Register input = ToRegister(instr->InputAt(0));
   4024   Register result = ToRegister(instr->result());
   4025   if (instr->needs_check()) {
   4026     STATIC_ASSERT(kHeapObjectTag == 1);
   4027     // If the input is a HeapObject, SmiUntag will set the carry flag.
   4028     __ SmiUntag(result, input, SetCC);
   4029     DeoptimizeIf(cs, instr->environment());
   4030   } else {
   4031     __ SmiUntag(result, input);
   4032   }
   4033 }
   4034 
   4035 
   4036 void LCodeGen::EmitNumberUntagD(Register input_reg,
   4037                                 DoubleRegister result_reg,
   4038                                 bool deoptimize_on_undefined,
   4039                                 bool deoptimize_on_minus_zero,
   4040                                 LEnvironment* env) {
   4041   Register scratch = scratch0();
   4042   SwVfpRegister flt_scratch = double_scratch0().low();
   4043   ASSERT(!result_reg.is(double_scratch0()));
   4044 
   4045   Label load_smi, heap_number, done;
   4046 
   4047   // Smi check.
   4048   __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
   4049 
   4050   // Heap number map check.
   4051   __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
   4052   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
   4053   __ cmp(scratch, Operand(ip));
   4054   if (deoptimize_on_undefined) {
   4055     DeoptimizeIf(ne, env);
   4056   } else {
   4057     Label heap_number;
   4058     __ b(eq, &heap_number);
   4059 
   4060     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   4061     __ cmp(input_reg, Operand(ip));
   4062     DeoptimizeIf(ne, env);
   4063 
   4064     // Convert undefined to NaN.
   4065     __ LoadRoot(ip, Heap::kNanValueRootIndex);
   4066     __ sub(ip, ip, Operand(kHeapObjectTag));
   4067     __ vldr(result_reg, ip, HeapNumber::kValueOffset);
   4068     __ jmp(&done);
   4069 
   4070     __ bind(&heap_number);
   4071   }
   4072   // Heap number to double register conversion.
   4073   __ sub(ip, input_reg, Operand(kHeapObjectTag));
   4074   __ vldr(result_reg, ip, HeapNumber::kValueOffset);
   4075   if (deoptimize_on_minus_zero) {
   4076     __ vmov(ip, result_reg.low());
   4077     __ cmp(ip, Operand(0));
   4078     __ b(ne, &done);
   4079     __ vmov(ip, result_reg.high());
   4080     __ cmp(ip, Operand(HeapNumber::kSignMask));
   4081     DeoptimizeIf(eq, env);
   4082   }
   4083   __ jmp(&done);
   4084 
   4085   // Smi to double register conversion
   4086   __ bind(&load_smi);
   4087   // scratch: untagged value of input_reg
   4088   __ vmov(flt_scratch, scratch);
   4089   __ vcvt_f64_s32(result_reg, flt_scratch);
   4090   __ bind(&done);
   4091 }
   4092 
   4093 
   4094 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
   4095   Register input_reg = ToRegister(instr->InputAt(0));
   4096   Register scratch1 = scratch0();
   4097   Register scratch2 = ToRegister(instr->TempAt(0));
   4098   DwVfpRegister double_scratch = double_scratch0();
   4099   SwVfpRegister single_scratch = double_scratch.low();
   4100 
   4101   ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
   4102   ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
   4103 
   4104   Label done;
   4105 
   4106   // The input was optimistically untagged; revert it.
   4107   // The carry flag is set when we reach this deferred code as we just executed
   4108   // SmiUntag(heap_object, SetCC)
   4109   STATIC_ASSERT(kHeapObjectTag == 1);
   4110   __ adc(input_reg, input_reg, Operand(input_reg));
   4111 
   4112   // Heap number map check.
   4113   __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
   4114   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
   4115   __ cmp(scratch1, Operand(ip));
   4116 
   4117   if (instr->truncating()) {
   4118     Register scratch3 = ToRegister(instr->TempAt(1));
   4119     DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2));
   4120     ASSERT(!scratch3.is(input_reg) &&
   4121            !scratch3.is(scratch1) &&
   4122            !scratch3.is(scratch2));
   4123     // Performs a truncating conversion of a floating point number as used by
   4124     // the JS bitwise operations.
   4125     Label heap_number;
   4126     __ b(eq, &heap_number);
   4127     // Check for undefined. Undefined is converted to zero for truncating
   4128     // conversions.
   4129     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   4130     __ cmp(input_reg, Operand(ip));
   4131     DeoptimizeIf(ne, instr->environment());
   4132     __ mov(input_reg, Operand(0));
   4133     __ b(&done);
   4134 
   4135     __ bind(&heap_number);
   4136     __ sub(scratch1, input_reg, Operand(kHeapObjectTag));
   4137     __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset);
   4138 
   4139     __ EmitECMATruncate(input_reg,
   4140                         double_scratch2,
   4141                         single_scratch,
   4142                         scratch1,
   4143                         scratch2,
   4144                         scratch3);
   4145 
   4146   } else {
   4147     CpuFeatures::Scope scope(VFP3);
   4148     // Deoptimize if we don't have a heap number.
   4149     DeoptimizeIf(ne, instr->environment());
   4150 
   4151     __ sub(ip, input_reg, Operand(kHeapObjectTag));
   4152     __ vldr(double_scratch, ip, HeapNumber::kValueOffset);
   4153     __ EmitVFPTruncate(kRoundToZero,
   4154                        single_scratch,
   4155                        double_scratch,
   4156                        scratch1,
   4157                        scratch2,
   4158                        kCheckForInexactConversion);
   4159     DeoptimizeIf(ne, instr->environment());
   4160     // Load the result.
   4161     __ vmov(input_reg, single_scratch);
   4162 
   4163     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
   4164       __ cmp(input_reg, Operand(0));
   4165       __ b(ne, &done);
   4166       __ vmov(scratch1, double_scratch.high());
   4167       __ tst(scratch1, Operand(HeapNumber::kSignMask));
   4168       DeoptimizeIf(ne, instr->environment());
   4169     }
   4170   }
   4171   __ bind(&done);
   4172 }
   4173 
   4174 
   4175 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
   4176   class DeferredTaggedToI: public LDeferredCode {
   4177    public:
   4178     DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
   4179         : LDeferredCode(codegen), instr_(instr) { }
   4180     virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
   4181     virtual LInstruction* instr() { return instr_; }
   4182    private:
   4183     LTaggedToI* instr_;
   4184   };
   4185 
   4186   LOperand* input = instr->InputAt(0);
   4187   ASSERT(input->IsRegister());
   4188   ASSERT(input->Equals(instr->result()));
   4189 
   4190   Register input_reg = ToRegister(input);
   4191 
   4192   DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr);
   4193 
   4194   // Optimistically untag the input.
   4195   // If the input is a HeapObject, SmiUntag will set the carry flag.
   4196   __ SmiUntag(input_reg, SetCC);
   4197   // Branch to deferred code if the input was tagged.
   4198   // The deferred code will take care of restoring the tag.
   4199   __ b(cs, deferred->entry());
   4200   __ bind(deferred->exit());
   4201 }
   4202 
   4203 
   4204 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
   4205   LOperand* input = instr->InputAt(0);
   4206   ASSERT(input->IsRegister());
   4207   LOperand* result = instr->result();
   4208   ASSERT(result->IsDoubleRegister());
   4209 
   4210   Register input_reg = ToRegister(input);
   4211   DoubleRegister result_reg = ToDoubleRegister(result);
   4212 
   4213   EmitNumberUntagD(input_reg, result_reg,
   4214                    instr->hydrogen()->deoptimize_on_undefined(),
   4215                    instr->hydrogen()->deoptimize_on_minus_zero(),
   4216                    instr->environment());
   4217 }
   4218 
   4219 
   4220 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
   4221   Register result_reg = ToRegister(instr->result());
   4222   Register scratch1 = scratch0();
   4223   Register scratch2 = ToRegister(instr->TempAt(0));
   4224   DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
   4225   SwVfpRegister single_scratch = double_scratch0().low();
   4226 
   4227   Label done;
   4228 
   4229   if (instr->truncating()) {
   4230     Register scratch3 = ToRegister(instr->TempAt(1));
   4231     __ EmitECMATruncate(result_reg,
   4232                         double_input,
   4233                         single_scratch,
   4234                         scratch1,
   4235                         scratch2,
   4236                         scratch3);
   4237   } else {
   4238     VFPRoundingMode rounding_mode = kRoundToMinusInf;
   4239     __ EmitVFPTruncate(rounding_mode,
   4240                        single_scratch,
   4241                        double_input,
   4242                        scratch1,
   4243                        scratch2,
   4244                        kCheckForInexactConversion);
   4245     // Deoptimize if we had a vfp invalid exception,
   4246     // including inexact operation.
   4247     DeoptimizeIf(ne, instr->environment());
   4248     // Retrieve the result.
   4249     __ vmov(result_reg, single_scratch);
   4250   }
   4251     __ bind(&done);
   4252 }
   4253 
   4254 
   4255 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
   4256   LOperand* input = instr->InputAt(0);
   4257   __ tst(ToRegister(input), Operand(kSmiTagMask));
   4258   DeoptimizeIf(ne, instr->environment());
   4259 }
   4260 
   4261 
   4262 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
   4263   LOperand* input = instr->InputAt(0);
   4264   __ tst(ToRegister(input), Operand(kSmiTagMask));
   4265   DeoptimizeIf(eq, instr->environment());
   4266 }
   4267 
   4268 
   4269 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   4270   Register input = ToRegister(instr->InputAt(0));
   4271   Register scratch = scratch0();
   4272 
   4273   __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
   4274   __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   4275 
   4276   if (instr->hydrogen()->is_interval_check()) {
   4277     InstanceType first;
   4278     InstanceType last;
   4279     instr->hydrogen()->GetCheckInterval(&first, &last);
   4280 
   4281     __ cmp(scratch, Operand(first));
   4282 
   4283     // If there is only one type in the interval check for equality.
   4284     if (first == last) {
   4285       DeoptimizeIf(ne, instr->environment());
   4286     } else {
   4287       DeoptimizeIf(lo, instr->environment());
   4288       // Omit check for the last type.
   4289       if (last != LAST_TYPE) {
   4290         __ cmp(scratch, Operand(last));
   4291         DeoptimizeIf(hi, instr->environment());
   4292       }
   4293     }
   4294   } else {
   4295     uint8_t mask;
   4296     uint8_t tag;
   4297     instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
   4298 
   4299     if (IsPowerOf2(mask)) {
   4300       ASSERT(tag == 0 || IsPowerOf2(tag));
   4301       __ tst(scratch, Operand(mask));
   4302       DeoptimizeIf(tag == 0 ? ne : eq, instr->environment());
   4303     } else {
   4304       __ and_(scratch, scratch, Operand(mask));
   4305       __ cmp(scratch, Operand(tag));
   4306       DeoptimizeIf(ne, instr->environment());
   4307     }
   4308   }
   4309 }
   4310 
   4311 
   4312 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
   4313   Register reg = ToRegister(instr->value());
   4314   Handle<JSFunction> target = instr->hydrogen()->target();
   4315   if (isolate()->heap()->InNewSpace(*target)) {
   4316     Register reg = ToRegister(instr->value());
   4317     Handle<JSGlobalPropertyCell> cell =
   4318         isolate()->factory()->NewJSGlobalPropertyCell(target);
   4319     __ mov(ip, Operand(Handle<Object>(cell)));
   4320     __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
   4321     __ cmp(reg, ip);
   4322   } else {
   4323     __ cmp(reg, Operand(target));
   4324   }
   4325   DeoptimizeIf(ne, instr->environment());
   4326 }
   4327 
   4328 
   4329 void LCodeGen::DoCheckMapCommon(Register reg,
   4330                                 Register scratch,
   4331                                 Handle<Map> map,
   4332                                 CompareMapMode mode,
   4333                                 LEnvironment* env) {
   4334   Label success;
   4335   __ CompareMap(reg, scratch, map, &success, mode);
   4336   DeoptimizeIf(ne, env);
   4337   __ bind(&success);
   4338 }
   4339 
   4340 
   4341 void LCodeGen::DoCheckMap(LCheckMap* instr) {
   4342   Register scratch = scratch0();
   4343   LOperand* input = instr->InputAt(0);
   4344   ASSERT(input->IsRegister());
   4345   Register reg = ToRegister(input);
   4346   Handle<Map> map = instr->hydrogen()->map();
   4347   DoCheckMapCommon(reg, scratch, map, instr->hydrogen()->mode(),
   4348                    instr->environment());
   4349 }
   4350 
   4351 
   4352 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
   4353   DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
   4354   Register result_reg = ToRegister(instr->result());
   4355   DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0));
   4356   __ ClampDoubleToUint8(result_reg, value_reg, temp_reg);
   4357 }
   4358 
   4359 
   4360 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
   4361   Register unclamped_reg = ToRegister(instr->unclamped());
   4362   Register result_reg = ToRegister(instr->result());
   4363   __ ClampUint8(result_reg, unclamped_reg);
   4364 }
   4365 
   4366 
   4367 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
   4368   Register scratch = scratch0();
   4369   Register input_reg = ToRegister(instr->unclamped());
   4370   Register result_reg = ToRegister(instr->result());
   4371   DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0));
   4372   Label is_smi, done, heap_number;
   4373 
   4374   // Both smi and heap number cases are handled.
   4375   __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi);
   4376 
   4377   // Check for heap number
   4378   __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
   4379   __ cmp(scratch, Operand(factory()->heap_number_map()));
   4380   __ b(eq, &heap_number);
   4381 
   4382   // Check for undefined. Undefined is converted to zero for clamping
   4383   // conversions.
   4384   __ cmp(input_reg, Operand(factory()->undefined_value()));
   4385   DeoptimizeIf(ne, instr->environment());
   4386   __ mov(result_reg, Operand(0));
   4387   __ jmp(&done);
   4388 
   4389   // Heap number
   4390   __ bind(&heap_number);
   4391   __ vldr(double_scratch0(), FieldMemOperand(input_reg,
   4392                                              HeapNumber::kValueOffset));
   4393   __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg);
   4394   __ jmp(&done);
   4395 
   4396   // smi
   4397   __ bind(&is_smi);
   4398   __ ClampUint8(result_reg, result_reg);
   4399 
   4400   __ bind(&done);
   4401 }
   4402 
   4403 
   4404 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
   4405   Register temp1 = ToRegister(instr->TempAt(0));
   4406   Register temp2 = ToRegister(instr->TempAt(1));
   4407 
   4408   Handle<JSObject> holder = instr->holder();
   4409   Handle<JSObject> current_prototype = instr->prototype();
   4410 
   4411   // Load prototype object.
   4412   __ LoadHeapObject(temp1, current_prototype);
   4413 
   4414   // Check prototype maps up to the holder.
   4415   while (!current_prototype.is_identical_to(holder)) {
   4416     DoCheckMapCommon(temp1, temp2,
   4417                      Handle<Map>(current_prototype->map()),
   4418                      ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
   4419     current_prototype =
   4420         Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
   4421     // Load next prototype object.
   4422     __ LoadHeapObject(temp1, current_prototype);
   4423   }
   4424 
   4425   // Check the holder map.
   4426   DoCheckMapCommon(temp1, temp2,
   4427                    Handle<Map>(current_prototype->map()),
   4428                    ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
   4429   DeoptimizeIf(ne, instr->environment());
   4430 }
   4431 
   4432 
   4433 void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
   4434   class DeferredAllocateObject: public LDeferredCode {
   4435    public:
   4436     DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
   4437         : LDeferredCode(codegen), instr_(instr) { }
   4438     virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
   4439     virtual LInstruction* instr() { return instr_; }
   4440    private:
   4441     LAllocateObject* instr_;
   4442   };
   4443 
   4444   DeferredAllocateObject* deferred = new DeferredAllocateObject(this, instr);
   4445 
   4446   Register result = ToRegister(instr->result());
   4447   Register scratch = ToRegister(instr->TempAt(0));
   4448   Register scratch2 = ToRegister(instr->TempAt(1));
   4449   Handle<JSFunction> constructor = instr->hydrogen()->constructor();
   4450   Handle<Map> initial_map(constructor->initial_map());
   4451   int instance_size = initial_map->instance_size();
   4452   ASSERT(initial_map->pre_allocated_property_fields() +
   4453          initial_map->unused_property_fields() -
   4454          initial_map->inobject_properties() == 0);
   4455 
   4456   // Allocate memory for the object.  The initial map might change when
   4457   // the constructor's prototype changes, but instance size and property
   4458   // counts remain unchanged (if slack tracking finished).
   4459   ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
   4460   __ AllocateInNewSpace(instance_size,
   4461                         result,
   4462                         scratch,
   4463                         scratch2,
   4464                         deferred->entry(),
   4465                         TAG_OBJECT);
   4466 
   4467   // Load the initial map.
   4468   Register map = scratch;
   4469   __ LoadHeapObject(map, constructor);
   4470   __ ldr(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset));
   4471 
   4472   // Initialize map and fields of the newly allocated object.
   4473   ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
   4474   __ str(map, FieldMemOperand(result, JSObject::kMapOffset));
   4475   __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
   4476   __ str(scratch, FieldMemOperand(result, JSObject::kElementsOffset));
   4477   __ str(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset));
   4478   if (initial_map->inobject_properties() != 0) {
   4479     __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
   4480     for (int i = 0; i < initial_map->inobject_properties(); i++) {
   4481       int property_offset = JSObject::kHeaderSize + i * kPointerSize;
   4482       __ str(scratch, FieldMemOperand(result, property_offset));
   4483     }
   4484   }
   4485 
   4486   __ bind(deferred->exit());
   4487 }
   4488 
   4489 
   4490 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
   4491   Register result = ToRegister(instr->result());
   4492   Handle<JSFunction> constructor = instr->hydrogen()->constructor();
   4493 
   4494   // TODO(3095996): Get rid of this. For now, we need to make the
   4495   // result register contain a valid pointer because it is already
   4496   // contained in the register pointer map.
   4497   __ mov(result, Operand(0));
   4498 
   4499   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   4500   __ LoadHeapObject(r0, constructor);
   4501   __ push(r0);
   4502   CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr);
   4503   __ StoreToSafepointRegisterSlot(r0, result);
   4504 }
   4505 
   4506 
   4507 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
   4508   Heap* heap = isolate()->heap();
   4509   ElementsKind boilerplate_elements_kind =
   4510       instr->hydrogen()->boilerplate_elements_kind();
   4511 
   4512   // Deopt if the array literal boilerplate ElementsKind is of a type different
   4513   // than the expected one. The check isn't necessary if the boilerplate has
   4514   // already been converted to FAST_ELEMENTS.
   4515   if (boilerplate_elements_kind != FAST_ELEMENTS) {
   4516     __ LoadHeapObject(r1, instr->hydrogen()->boilerplate_object());
   4517     // Load map into r2.
   4518     __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
   4519     // Load the map's "bit field 2".
   4520     __ ldrb(r2, FieldMemOperand(r2, Map::kBitField2Offset));
   4521     // Retrieve elements_kind from bit field 2.
   4522     __ ubfx(r2, r2, Map::kElementsKindShift, Map::kElementsKindBitCount);
   4523     __ cmp(r2, Operand(boilerplate_elements_kind));
   4524     DeoptimizeIf(ne, instr->environment());
   4525   }
   4526 
   4527   __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   4528   __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
   4529   __ mov(r2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
   4530   // Boilerplate already exists, constant elements are never accessed.
   4531   // Pass an empty fixed array.
   4532   __ mov(r1, Operand(Handle<FixedArray>(heap->empty_fixed_array())));
   4533   __ Push(r3, r2, r1);
   4534 
   4535   // Pick the right runtime function or stub to call.
   4536   int length = instr->hydrogen()->length();
   4537   if (instr->hydrogen()->IsCopyOnWrite()) {
   4538     ASSERT(instr->hydrogen()->depth() == 1);
   4539     FastCloneShallowArrayStub::Mode mode =
   4540         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
   4541     FastCloneShallowArrayStub stub(mode, length);
   4542     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   4543   } else if (instr->hydrogen()->depth() > 1) {
   4544     CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
   4545   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
   4546     CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
   4547   } else {
   4548     FastCloneShallowArrayStub::Mode mode =
   4549         boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS
   4550             ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
   4551             : FastCloneShallowArrayStub::CLONE_ELEMENTS;
   4552     FastCloneShallowArrayStub stub(mode, length);
   4553     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   4554   }
   4555 }
   4556 
   4557 
   4558 void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
   4559                             Register result,
   4560                             Register source,
   4561                             int* offset) {
   4562   ASSERT(!source.is(r2));
   4563   ASSERT(!result.is(r2));
   4564 
   4565   // Only elements backing stores for non-COW arrays need to be copied.
   4566   Handle<FixedArrayBase> elements(object->elements());
   4567   bool has_elements = elements->length() > 0 &&
   4568       elements->map() != isolate()->heap()->fixed_cow_array_map();
   4569 
   4570   // Increase the offset so that subsequent objects end up right after
   4571   // this object and its backing store.
   4572   int object_offset = *offset;
   4573   int object_size = object->map()->instance_size();
   4574   int elements_offset = *offset + object_size;
   4575   int elements_size = has_elements ? elements->Size() : 0;
   4576   *offset += object_size + elements_size;
   4577 
   4578   // Copy object header.
   4579   ASSERT(object->properties()->length() == 0);
   4580   int inobject_properties = object->map()->inobject_properties();
   4581   int header_size = object_size - inobject_properties * kPointerSize;
   4582   for (int i = 0; i < header_size; i += kPointerSize) {
   4583     if (has_elements && i == JSObject::kElementsOffset) {
   4584       __ add(r2, result, Operand(elements_offset));
   4585     } else {
   4586       __ ldr(r2, FieldMemOperand(source, i));
   4587     }
   4588     __ str(r2, FieldMemOperand(result, object_offset + i));
   4589   }
   4590 
   4591   // Copy in-object properties.
   4592   for (int i = 0; i < inobject_properties; i++) {
   4593     int total_offset = object_offset + object->GetInObjectPropertyOffset(i);
   4594     Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i));
   4595     if (value->IsJSObject()) {
   4596       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   4597       __ add(r2, result, Operand(*offset));
   4598       __ str(r2, FieldMemOperand(result, total_offset));
   4599       __ LoadHeapObject(source, value_object);
   4600       EmitDeepCopy(value_object, result, source, offset);
   4601     } else if (value->IsHeapObject()) {
   4602       __ LoadHeapObject(r2, Handle<HeapObject>::cast(value));
   4603       __ str(r2, FieldMemOperand(result, total_offset));
   4604     } else {
   4605       __ mov(r2, Operand(value));
   4606       __ str(r2, FieldMemOperand(result, total_offset));
   4607     }
   4608   }
   4609 
   4610   if (has_elements) {
   4611     // Copy elements backing store header.
   4612     __ LoadHeapObject(source, elements);
   4613     for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) {
   4614       __ ldr(r2, FieldMemOperand(source, i));
   4615       __ str(r2, FieldMemOperand(result, elements_offset + i));
   4616     }
   4617 
   4618     // Copy elements backing store content.
   4619     int elements_length = has_elements ? elements->length() : 0;
   4620     if (elements->IsFixedDoubleArray()) {
   4621       Handle<FixedDoubleArray> double_array =
   4622           Handle<FixedDoubleArray>::cast(elements);
   4623       for (int i = 0; i < elements_length; i++) {
   4624         int64_t value = double_array->get_representation(i);
   4625         // We only support little endian mode...
   4626         int32_t value_low = value & 0xFFFFFFFF;
   4627         int32_t value_high = value >> 32;
   4628         int total_offset =
   4629             elements_offset + FixedDoubleArray::OffsetOfElementAt(i);
   4630         __ mov(r2, Operand(value_low));
   4631         __ str(r2, FieldMemOperand(result, total_offset));
   4632         __ mov(r2, Operand(value_high));
   4633         __ str(r2, FieldMemOperand(result, total_offset + 4));
   4634       }
   4635     } else if (elements->IsFixedArray()) {
   4636       for (int i = 0; i < elements_length; i++) {
   4637         int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
   4638         Handle<Object> value = JSObject::GetElement(object, i);
   4639         if (value->IsJSObject()) {
   4640           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   4641           __ add(r2, result, Operand(*offset));
   4642           __ str(r2, FieldMemOperand(result, total_offset));
   4643           __ LoadHeapObject(source, value_object);
   4644           EmitDeepCopy(value_object, result, source, offset);
   4645         } else if (value->IsHeapObject()) {
   4646           __ LoadHeapObject(r2, Handle<HeapObject>::cast(value));
   4647           __ str(r2, FieldMemOperand(result, total_offset));
   4648         } else {
   4649           __ mov(r2, Operand(value));
   4650           __ str(r2, FieldMemOperand(result, total_offset));
   4651         }
   4652       }
   4653     } else {
   4654       UNREACHABLE();
   4655     }
   4656   }
   4657 }
   4658 
   4659 
   4660 void LCodeGen::DoFastLiteral(LFastLiteral* instr) {
   4661   int size = instr->hydrogen()->total_size();
   4662 
   4663   // Allocate all objects that are part of the literal in one big
   4664   // allocation. This avoids multiple limit checks.
   4665   Label allocated, runtime_allocate;
   4666   __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
   4667   __ jmp(&allocated);
   4668 
   4669   __ bind(&runtime_allocate);
   4670   __ mov(r0, Operand(Smi::FromInt(size)));
   4671   __ push(r0);
   4672   CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
   4673 
   4674   __ bind(&allocated);
   4675   int offset = 0;
   4676   __ LoadHeapObject(r1, instr->hydrogen()->boilerplate());
   4677   EmitDeepCopy(instr->hydrogen()->boilerplate(), r0, r1, &offset);
   4678   ASSERT_EQ(size, offset);
   4679 }
   4680 
   4681 
   4682 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
   4683   Handle<FixedArray> literals(instr->environment()->closure()->literals());
   4684   Handle<FixedArray> constant_properties =
   4685       instr->hydrogen()->constant_properties();
   4686 
   4687   // Set up the parameters to the stub/runtime call.
   4688   __ LoadHeapObject(r4, literals);
   4689   __ mov(r3, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
   4690   __ mov(r2, Operand(constant_properties));
   4691   int flags = instr->hydrogen()->fast_elements()
   4692       ? ObjectLiteral::kFastElements
   4693       : ObjectLiteral::kNoFlags;
   4694   __ mov(r1, Operand(Smi::FromInt(flags)));
   4695   __ Push(r4, r3, r2, r1);
   4696 
   4697   // Pick the right runtime function or stub to call.
   4698   int properties_count = constant_properties->length() / 2;
   4699   if (instr->hydrogen()->depth() > 1) {
   4700     CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
   4701   } else if (flags != ObjectLiteral::kFastElements ||
   4702       properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
   4703     CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
   4704   } else {
   4705     FastCloneShallowObjectStub stub(properties_count);
   4706     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   4707   }
   4708 }
   4709 
   4710 
   4711 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
   4712   ASSERT(ToRegister(instr->InputAt(0)).is(r0));
   4713   __ push(r0);
   4714   CallRuntime(Runtime::kToFastProperties, 1, instr);
   4715 }
   4716 
   4717 
   4718 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   4719   Label materialized;
   4720   // Registers will be used as follows:
   4721   // r3 = JS function.
   4722   // r7 = literals array.
   4723   // r1 = regexp literal.
   4724   // r0 = regexp literal clone.
   4725   // r2 and r4-r6 are used as temporaries.
   4726   __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   4727   __ ldr(r7, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
   4728   int literal_offset = FixedArray::kHeaderSize +
   4729       instr->hydrogen()->literal_index() * kPointerSize;
   4730   __ ldr(r1, FieldMemOperand(r7, literal_offset));
   4731   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   4732   __ cmp(r1, ip);
   4733   __ b(ne, &materialized);
   4734 
   4735   // Create regexp literal using runtime function
   4736   // Result will be in r0.
   4737   __ mov(r6, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
   4738   __ mov(r5, Operand(instr->hydrogen()->pattern()));
   4739   __ mov(r4, Operand(instr->hydrogen()->flags()));
   4740   __ Push(r7, r6, r5, r4);
   4741   CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
   4742   __ mov(r1, r0);
   4743 
   4744   __ bind(&materialized);
   4745   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
   4746   Label allocated, runtime_allocate;
   4747 
   4748   __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
   4749   __ jmp(&allocated);
   4750 
   4751   __ bind(&runtime_allocate);
   4752   __ mov(r0, Operand(Smi::FromInt(size)));
   4753   __ Push(r1, r0);
   4754   CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
   4755   __ pop(r1);
   4756 
   4757   __ bind(&allocated);
   4758   // Copy the content into the newly allocated memory.
   4759   // (Unroll copy loop once for better throughput).
   4760   for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
   4761     __ ldr(r3, FieldMemOperand(r1, i));
   4762     __ ldr(r2, FieldMemOperand(r1, i + kPointerSize));
   4763     __ str(r3, FieldMemOperand(r0, i));
   4764     __ str(r2, FieldMemOperand(r0, i + kPointerSize));
   4765   }
   4766   if ((size % (2 * kPointerSize)) != 0) {
   4767     __ ldr(r3, FieldMemOperand(r1, size - kPointerSize));
   4768     __ str(r3, FieldMemOperand(r0, size - kPointerSize));
   4769   }
   4770 }
   4771 
   4772 
   4773 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   4774   // Use the fast case closure allocation code that allocates in new
   4775   // space for nested functions that don't need literals cloning.
   4776   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   4777   bool pretenure = instr->hydrogen()->pretenure();
   4778   if (!pretenure && shared_info->num_literals() == 0) {
   4779     FastNewClosureStub stub(shared_info->language_mode());
   4780     __ mov(r1, Operand(shared_info));
   4781     __ push(r1);
   4782     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   4783   } else {
   4784     __ mov(r2, Operand(shared_info));
   4785     __ mov(r1, Operand(pretenure
   4786                        ? factory()->true_value()
   4787                        : factory()->false_value()));
   4788     __ Push(cp, r2, r1);
   4789     CallRuntime(Runtime::kNewClosure, 3, instr);
   4790   }
   4791 }
   4792 
   4793 
   4794 void LCodeGen::DoTypeof(LTypeof* instr) {
   4795   Register input = ToRegister(instr->InputAt(0));
   4796   __ push(input);
   4797   CallRuntime(Runtime::kTypeof, 1, instr);
   4798 }
   4799 
   4800 
   4801 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
   4802   Register input = ToRegister(instr->InputAt(0));
   4803   int true_block = chunk_->LookupDestination(instr->true_block_id());
   4804   int false_block = chunk_->LookupDestination(instr->false_block_id());
   4805   Label* true_label = chunk_->GetAssemblyLabel(true_block);
   4806   Label* false_label = chunk_->GetAssemblyLabel(false_block);
   4807 
   4808   Condition final_branch_condition = EmitTypeofIs(true_label,
   4809                                                   false_label,
   4810                                                   input,
   4811                                                   instr->type_literal());
   4812   if (final_branch_condition != kNoCondition) {
   4813     EmitBranch(true_block, false_block, final_branch_condition);
   4814   }
   4815 }
   4816 
   4817 
   4818 Condition LCodeGen::EmitTypeofIs(Label* true_label,
   4819                                  Label* false_label,
   4820                                  Register input,
   4821                                  Handle<String> type_name) {
   4822   Condition final_branch_condition = kNoCondition;
   4823   Register scratch = scratch0();
   4824   if (type_name->Equals(heap()->number_symbol())) {
   4825     __ JumpIfSmi(input, true_label);
   4826     __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
   4827     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
   4828     __ cmp(input, Operand(ip));
   4829     final_branch_condition = eq;
   4830 
   4831   } else if (type_name->Equals(heap()->string_symbol())) {
   4832     __ JumpIfSmi(input, false_label);
   4833     __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
   4834     __ b(ge, false_label);
   4835     __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
   4836     __ tst(ip, Operand(1 << Map::kIsUndetectable));
   4837     final_branch_condition = eq;
   4838 
   4839   } else if (type_name->Equals(heap()->boolean_symbol())) {
   4840     __ CompareRoot(input, Heap::kTrueValueRootIndex);
   4841     __ b(eq, true_label);
   4842     __ CompareRoot(input, Heap::kFalseValueRootIndex);
   4843     final_branch_condition = eq;
   4844 
   4845   } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) {
   4846     __ CompareRoot(input, Heap::kNullValueRootIndex);
   4847     final_branch_condition = eq;
   4848 
   4849   } else if (type_name->Equals(heap()->undefined_symbol())) {
   4850     __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
   4851     __ b(eq, true_label);
   4852     __ JumpIfSmi(input, false_label);
   4853     // Check for undetectable objects => true.
   4854     __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
   4855     __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
   4856     __ tst(ip, Operand(1 << Map::kIsUndetectable));
   4857     final_branch_condition = ne;
   4858 
   4859   } else if (type_name->Equals(heap()->function_symbol())) {
   4860     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
   4861     __ JumpIfSmi(input, false_label);
   4862     __ CompareObjectType(input, scratch, input, JS_FUNCTION_TYPE);
   4863     __ b(eq, true_label);
   4864     __ cmp(input, Operand(JS_FUNCTION_PROXY_TYPE));
   4865     final_branch_condition = eq;
   4866 
   4867   } else if (type_name->Equals(heap()->object_symbol())) {
   4868     __ JumpIfSmi(input, false_label);
   4869     if (!FLAG_harmony_typeof) {
   4870       __ CompareRoot(input, Heap::kNullValueRootIndex);
   4871       __ b(eq, true_label);
   4872     }
   4873     __ CompareObjectType(input, input, scratch,
   4874                          FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
   4875     __ b(lt, false_label);
   4876     __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
   4877     __ b(gt, false_label);
   4878     // Check for undetectable objects => false.
   4879     __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
   4880     __ tst(ip, Operand(1 << Map::kIsUndetectable));
   4881     final_branch_condition = eq;
   4882 
   4883   } else {
   4884     __ b(false_label);
   4885   }
   4886 
   4887   return final_branch_condition;
   4888 }
   4889 
   4890 
   4891 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
   4892   Register temp1 = ToRegister(instr->TempAt(0));
   4893   int true_block = chunk_->LookupDestination(instr->true_block_id());
   4894   int false_block = chunk_->LookupDestination(instr->false_block_id());
   4895 
   4896   EmitIsConstructCall(temp1, scratch0());
   4897   EmitBranch(true_block, false_block, eq);
   4898 }
   4899 
   4900 
   4901 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
   4902   ASSERT(!temp1.is(temp2));
   4903   // Get the frame pointer for the calling frame.
   4904   __ ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   4905 
   4906   // Skip the arguments adaptor frame if it exists.
   4907   Label check_frame_marker;
   4908   __ ldr(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
   4909   __ cmp(temp2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   4910   __ b(ne, &check_frame_marker);
   4911   __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
   4912 
   4913   // Check the marker in the calling frame.
   4914   __ bind(&check_frame_marker);
   4915   __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
   4916   __ cmp(temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
   4917 }
   4918 
   4919 
   4920 void LCodeGen::EnsureSpaceForLazyDeopt() {
   4921   // Ensure that we have enough space after the previous lazy-bailout
   4922   // instruction for patching the code here.
   4923   int current_pc = masm()->pc_offset();
   4924   int patch_size = Deoptimizer::patch_size();
   4925   if (current_pc < last_lazy_deopt_pc_ + patch_size) {
   4926     int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc;
   4927     ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
   4928     while (padding_size > 0) {
   4929       __ nop();
   4930       padding_size -= Assembler::kInstrSize;
   4931     }
   4932   }
   4933   last_lazy_deopt_pc_ = masm()->pc_offset();
   4934 }
   4935 
   4936 
   4937 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
   4938   EnsureSpaceForLazyDeopt();
   4939   ASSERT(instr->HasEnvironment());
   4940   LEnvironment* env = instr->environment();
   4941   RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
   4942   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
   4943 }
   4944 
   4945 
   4946 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
   4947   DeoptimizeIf(al, instr->environment());
   4948 }
   4949 
   4950 
   4951 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
   4952   Register object = ToRegister(instr->object());
   4953   Register key = ToRegister(instr->key());
   4954   Register strict = scratch0();
   4955   __ mov(strict, Operand(Smi::FromInt(strict_mode_flag())));
   4956   __ Push(object, key, strict);
   4957   ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
   4958   LPointerMap* pointers = instr->pointer_map();
   4959   RecordPosition(pointers->position());
   4960   SafepointGenerator safepoint_generator(
   4961       this, pointers, Safepoint::kLazyDeopt);
   4962   __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
   4963 }
   4964 
   4965 
   4966 void LCodeGen::DoIn(LIn* instr) {
   4967   Register obj = ToRegister(instr->object());
   4968   Register key = ToRegister(instr->key());
   4969   __ Push(key, obj);
   4970   ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
   4971   LPointerMap* pointers = instr->pointer_map();
   4972   RecordPosition(pointers->position());
   4973   SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
   4974   __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
   4975 }
   4976 
   4977 
   4978 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
   4979   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   4980   __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
   4981   RecordSafepointWithLazyDeopt(
   4982       instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
   4983   ASSERT(instr->HasEnvironment());
   4984   LEnvironment* env = instr->environment();
   4985   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
   4986 }
   4987 
   4988 
   4989 void LCodeGen::DoStackCheck(LStackCheck* instr) {
   4990   class DeferredStackCheck: public LDeferredCode {
   4991    public:
   4992     DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
   4993         : LDeferredCode(codegen), instr_(instr) { }
   4994     virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
   4995     virtual LInstruction* instr() { return instr_; }
   4996    private:
   4997     LStackCheck* instr_;
   4998   };
   4999 
   5000   ASSERT(instr->HasEnvironment());
   5001   LEnvironment* env = instr->environment();
   5002   // There is no LLazyBailout instruction for stack-checks. We have to
   5003   // prepare for lazy deoptimization explicitly here.
   5004   if (instr->hydrogen()->is_function_entry()) {
   5005     // Perform stack overflow check.
   5006     Label done;
   5007     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
   5008     __ cmp(sp, Operand(ip));
   5009     __ b(hs, &done);
   5010     StackCheckStub stub;
   5011     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   5012     EnsureSpaceForLazyDeopt();
   5013     __ bind(&done);
   5014     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
   5015     safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
   5016   } else {
   5017     ASSERT(instr->hydrogen()->is_backwards_branch());
   5018     // Perform stack overflow check if this goto needs it before jumping.
   5019     DeferredStackCheck* deferred_stack_check =
   5020         new DeferredStackCheck(this, instr);
   5021     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
   5022     __ cmp(sp, Operand(ip));
   5023     __ b(lo, deferred_stack_check->entry());
   5024     EnsureSpaceForLazyDeopt();
   5025     __ bind(instr->done_label());
   5026     deferred_stack_check->SetExit(instr->done_label());
   5027     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
   5028     // Don't record a deoptimization index for the safepoint here.
   5029     // This will be done explicitly when emitting call and the safepoint in
   5030     // the deferred code.
   5031   }
   5032 }
   5033 
   5034 
   5035 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
   5036   // This is a pseudo-instruction that ensures that the environment here is
   5037   // properly registered for deoptimization and records the assembler's PC
   5038   // offset.
   5039   LEnvironment* environment = instr->environment();
   5040   environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
   5041                                    instr->SpilledDoubleRegisterArray());
   5042 
   5043   // If the environment were already registered, we would have no way of
   5044   // backpatching it with the spill slot operands.
   5045   ASSERT(!environment->HasBeenRegistered());
   5046   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
   5047   ASSERT(osr_pc_offset_ == -1);
   5048   osr_pc_offset_ = masm()->pc_offset();
   5049 }
   5050 
   5051 
   5052 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
   5053   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   5054   __ cmp(r0, ip);
   5055   DeoptimizeIf(eq, instr->environment());
   5056 
   5057   Register null_value = r5;
   5058   __ LoadRoot(null_value, Heap::kNullValueRootIndex);
   5059   __ cmp(r0, null_value);
   5060   DeoptimizeIf(eq, instr->environment());
   5061 
   5062   __ tst(r0, Operand(kSmiTagMask));
   5063   DeoptimizeIf(eq, instr->environment());
   5064 
   5065   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
   5066   __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
   5067   DeoptimizeIf(le, instr->environment());
   5068 
   5069   Label use_cache, call_runtime;
   5070   __ CheckEnumCache(null_value, &call_runtime);
   5071 
   5072   __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
   5073   __ b(&use_cache);
   5074 
   5075   // Get the set of properties to enumerate.
   5076   __ bind(&call_runtime);
   5077   __ push(r0);
   5078   CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
   5079 
   5080   __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
   5081   __ LoadRoot(ip, Heap::kMetaMapRootIndex);
   5082   __ cmp(r1, ip);
   5083   DeoptimizeIf(ne, instr->environment());
   5084   __ bind(&use_cache);
   5085 }
   5086 
   5087 
   5088 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
   5089   Register map = ToRegister(instr->map());
   5090   Register result = ToRegister(instr->result());
   5091   __ LoadInstanceDescriptors(map, result);
   5092   __ ldr(result,
   5093          FieldMemOperand(result, DescriptorArray::kEnumerationIndexOffset));
   5094   __ ldr(result,
   5095          FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
   5096   __ cmp(result, Operand(0));
   5097   DeoptimizeIf(eq, instr->environment());
   5098 }
   5099 
   5100 
   5101 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
   5102   Register object = ToRegister(instr->value());
   5103   Register map = ToRegister(instr->map());
   5104   __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
   5105   __ cmp(map, scratch0());
   5106   DeoptimizeIf(ne, instr->environment());
   5107 }
   5108 
   5109 
   5110 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
   5111   Register object = ToRegister(instr->object());
   5112   Register index = ToRegister(instr->index());
   5113   Register result = ToRegister(instr->result());
   5114   Register scratch = scratch0();
   5115 
   5116   Label out_of_object, done;
   5117   __ cmp(index, Operand(0));
   5118   __ b(lt, &out_of_object);
   5119 
   5120   STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize);
   5121   __ add(scratch, object, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize));
   5122   __ ldr(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
   5123 
   5124   __ b(&done);
   5125 
   5126   __ bind(&out_of_object);
   5127   __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
   5128   // Index is equal to negated out of object property index plus 1.
   5129   __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize));
   5130   __ ldr(result, FieldMemOperand(scratch,
   5131                                  FixedArray::kHeaderSize - kPointerSize));
   5132   __ bind(&done);
   5133 }
   5134 
   5135 
   5136 #undef __
   5137 
   5138 } }  // namespace v8::internal
   5139