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 #if defined(V8_TARGET_ARCH_ARM)
     31 
     32 #include "code-stubs.h"
     33 #include "codegen.h"
     34 #include "compiler.h"
     35 #include "debug.h"
     36 #include "full-codegen.h"
     37 #include "isolate-inl.h"
     38 #include "parser.h"
     39 #include "scopes.h"
     40 #include "stub-cache.h"
     41 
     42 #include "arm/code-stubs-arm.h"
     43 #include "arm/macro-assembler-arm.h"
     44 
     45 namespace v8 {
     46 namespace internal {
     47 
     48 #define __ ACCESS_MASM(masm_)
     49 
     50 
     51 // A patch site is a location in the code which it is possible to patch. This
     52 // class has a number of methods to emit the code which is patchable and the
     53 // method EmitPatchInfo to record a marker back to the patchable code. This
     54 // marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit
     55 // immediate value is used) is the delta from the pc to the first instruction of
     56 // the patchable code.
     57 class JumpPatchSite BASE_EMBEDDED {
     58  public:
     59   explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
     60 #ifdef DEBUG
     61     info_emitted_ = false;
     62 #endif
     63   }
     64 
     65   ~JumpPatchSite() {
     66     ASSERT(patch_site_.is_bound() == info_emitted_);
     67   }
     68 
     69   // When initially emitting this ensure that a jump is always generated to skip
     70   // the inlined smi code.
     71   void EmitJumpIfNotSmi(Register reg, Label* target) {
     72     ASSERT(!patch_site_.is_bound() && !info_emitted_);
     73     Assembler::BlockConstPoolScope block_const_pool(masm_);
     74     __ bind(&patch_site_);
     75     __ cmp(reg, Operand(reg));
     76     // Don't use b(al, ...) as that might emit the constant pool right after the
     77     // branch. After patching when the branch is no longer unconditional
     78     // execution can continue into the constant pool.
     79     __ b(eq, target);  // Always taken before patched.
     80   }
     81 
     82   // When initially emitting this ensure that a jump is never generated to skip
     83   // the inlined smi code.
     84   void EmitJumpIfSmi(Register reg, Label* target) {
     85     ASSERT(!patch_site_.is_bound() && !info_emitted_);
     86     Assembler::BlockConstPoolScope block_const_pool(masm_);
     87     __ bind(&patch_site_);
     88     __ cmp(reg, Operand(reg));
     89     __ b(ne, target);  // Never taken before patched.
     90   }
     91 
     92   void EmitPatchInfo() {
     93     if (patch_site_.is_bound()) {
     94       int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
     95       Register reg;
     96       reg.set_code(delta_to_patch_site / kOff12Mask);
     97       __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask);
     98 #ifdef DEBUG
     99       info_emitted_ = true;
    100 #endif
    101     } else {
    102       __ nop();  // Signals no inlined code.
    103     }
    104   }
    105 
    106  private:
    107   MacroAssembler* masm_;
    108   Label patch_site_;
    109 #ifdef DEBUG
    110   bool info_emitted_;
    111 #endif
    112 };
    113 
    114 
    115 // TODO(jkummerow): Obsolete as soon as x64 is updated. Remove.
    116 int FullCodeGenerator::self_optimization_header_size() {
    117   UNREACHABLE();
    118   return 24;
    119 }
    120 
    121 
    122 // Generate code for a JS function.  On entry to the function the receiver
    123 // and arguments have been pushed on the stack left to right.  The actual
    124 // argument count matches the formal parameter count expected by the
    125 // function.
    126 //
    127 // The live registers are:
    128 //   o r1: the JS function object being called (i.e., ourselves)
    129 //   o cp: our context
    130 //   o fp: our caller's frame pointer
    131 //   o sp: stack pointer
    132 //   o lr: return address
    133 //
    134 // The function builds a JS frame.  Please see JavaScriptFrameConstants in
    135 // frames-arm.h for its layout.
    136 void FullCodeGenerator::Generate() {
    137   CompilationInfo* info = info_;
    138   handler_table_ =
    139       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
    140   profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
    141       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget)));
    142   SetFunctionPosition(function());
    143   Comment cmnt(masm_, "[ function compiled by full code generator");
    144 
    145 #ifdef DEBUG
    146   if (strlen(FLAG_stop_at) > 0 &&
    147       info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
    148     __ stop("stop-at");
    149   }
    150 #endif
    151 
    152   // Strict mode functions and builtins need to replace the receiver
    153   // with undefined when called as functions (without an explicit
    154   // receiver object). r5 is zero for method calls and non-zero for
    155   // function calls.
    156   if (!info->is_classic_mode() || info->is_native()) {
    157     Label ok;
    158     __ cmp(r5, Operand(0));
    159     __ b(eq, &ok);
    160     int receiver_offset = info->scope()->num_parameters() * kPointerSize;
    161     __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
    162     __ str(r2, MemOperand(sp, receiver_offset));
    163     __ bind(&ok);
    164   }
    165 
    166   // Open a frame scope to indicate that there is a frame on the stack.  The
    167   // MANUAL indicates that the scope shouldn't actually generate code to set up
    168   // the frame (that is done below).
    169   FrameScope frame_scope(masm_, StackFrame::MANUAL);
    170 
    171   int locals_count = info->scope()->num_stack_slots();
    172 
    173   __ Push(lr, fp, cp, r1);
    174   if (locals_count > 0) {
    175     // Load undefined value here, so the value is ready for the loop
    176     // below.
    177     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
    178   }
    179   // Adjust fp to point to caller's fp.
    180   __ add(fp, sp, Operand(2 * kPointerSize));
    181 
    182   { Comment cmnt(masm_, "[ Allocate locals");
    183     for (int i = 0; i < locals_count; i++) {
    184       __ push(ip);
    185     }
    186   }
    187 
    188   bool function_in_register = true;
    189 
    190   // Possibly allocate a local context.
    191   int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
    192   if (heap_slots > 0) {
    193     Comment cmnt(masm_, "[ Allocate local context");
    194     // Argument to NewContext is the function, which is in r1.
    195     __ push(r1);
    196     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
    197       FastNewContextStub stub(heap_slots);
    198       __ CallStub(&stub);
    199     } else {
    200       __ CallRuntime(Runtime::kNewFunctionContext, 1);
    201     }
    202     function_in_register = false;
    203     // Context is returned in both r0 and cp.  It replaces the context
    204     // passed to us.  It's saved in the stack and kept live in cp.
    205     __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
    206     // Copy any necessary parameters into the context.
    207     int num_parameters = info->scope()->num_parameters();
    208     for (int i = 0; i < num_parameters; i++) {
    209       Variable* var = scope()->parameter(i);
    210       if (var->IsContextSlot()) {
    211         int parameter_offset = StandardFrameConstants::kCallerSPOffset +
    212             (num_parameters - 1 - i) * kPointerSize;
    213         // Load parameter from stack.
    214         __ ldr(r0, MemOperand(fp, parameter_offset));
    215         // Store it in the context.
    216         MemOperand target = ContextOperand(cp, var->index());
    217         __ str(r0, target);
    218 
    219         // Update the write barrier.
    220         __ RecordWriteContextSlot(
    221             cp, target.offset(), r0, r3, kLRHasBeenSaved, kDontSaveFPRegs);
    222       }
    223     }
    224   }
    225 
    226   Variable* arguments = scope()->arguments();
    227   if (arguments != NULL) {
    228     // Function uses arguments object.
    229     Comment cmnt(masm_, "[ Allocate arguments object");
    230     if (!function_in_register) {
    231       // Load this again, if it's used by the local context below.
    232       __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
    233     } else {
    234       __ mov(r3, r1);
    235     }
    236     // Receiver is just before the parameters on the caller's stack.
    237     int num_parameters = info->scope()->num_parameters();
    238     int offset = num_parameters * kPointerSize;
    239     __ add(r2, fp,
    240            Operand(StandardFrameConstants::kCallerSPOffset + offset));
    241     __ mov(r1, Operand(Smi::FromInt(num_parameters)));
    242     __ Push(r3, r2, r1);
    243 
    244     // Arguments to ArgumentsAccessStub:
    245     //   function, receiver address, parameter count.
    246     // The stub will rewrite receiever and parameter count if the previous
    247     // stack frame was an arguments adapter frame.
    248     ArgumentsAccessStub::Type type;
    249     if (!is_classic_mode()) {
    250       type = ArgumentsAccessStub::NEW_STRICT;
    251     } else if (function()->has_duplicate_parameters()) {
    252       type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
    253     } else {
    254       type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
    255     }
    256     ArgumentsAccessStub stub(type);
    257     __ CallStub(&stub);
    258 
    259     SetVar(arguments, r0, r1, r2);
    260   }
    261 
    262   if (FLAG_trace) {
    263     __ CallRuntime(Runtime::kTraceEnter, 0);
    264   }
    265 
    266   // Visit the declarations and body unless there is an illegal
    267   // redeclaration.
    268   if (scope()->HasIllegalRedeclaration()) {
    269     Comment cmnt(masm_, "[ Declarations");
    270     scope()->VisitIllegalRedeclaration(this);
    271 
    272   } else {
    273     PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
    274     { Comment cmnt(masm_, "[ Declarations");
    275       // For named function expressions, declare the function name as a
    276       // constant.
    277       if (scope()->is_function_scope() && scope()->function() != NULL) {
    278         VariableProxy* proxy = scope()->function();
    279         ASSERT(proxy->var()->mode() == CONST ||
    280                proxy->var()->mode() == CONST_HARMONY);
    281         ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
    282         EmitDeclaration(proxy, proxy->var()->mode(), NULL);
    283       }
    284       VisitDeclarations(scope()->declarations());
    285     }
    286 
    287     { Comment cmnt(masm_, "[ Stack check");
    288       PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
    289       Label ok;
    290       __ LoadRoot(ip, Heap::kStackLimitRootIndex);
    291       __ cmp(sp, Operand(ip));
    292       __ b(hs, &ok);
    293       StackCheckStub stub;
    294       __ CallStub(&stub);
    295       __ bind(&ok);
    296     }
    297 
    298     { Comment cmnt(masm_, "[ Body");
    299       ASSERT(loop_depth() == 0);
    300       VisitStatements(function()->body());
    301       ASSERT(loop_depth() == 0);
    302     }
    303   }
    304 
    305   // Always emit a 'return undefined' in case control fell off the end of
    306   // the body.
    307   { Comment cmnt(masm_, "[ return <undefined>;");
    308     __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
    309   }
    310   EmitReturnSequence();
    311 
    312   // Force emit the constant pool, so it doesn't get emitted in the middle
    313   // of the stack check table.
    314   masm()->CheckConstPool(true, false);
    315 }
    316 
    317 
    318 void FullCodeGenerator::ClearAccumulator() {
    319   __ mov(r0, Operand(Smi::FromInt(0)));
    320 }
    321 
    322 
    323 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
    324   __ mov(r2, Operand(profiling_counter_));
    325   __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
    326   __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC);
    327   __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
    328 }
    329 
    330 
    331 void FullCodeGenerator::EmitProfilingCounterReset() {
    332   int reset_value = FLAG_interrupt_budget;
    333   if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
    334     // Self-optimization is a one-off thing: if it fails, don't try again.
    335     reset_value = Smi::kMaxValue;
    336   }
    337   if (isolate()->IsDebuggerActive()) {
    338     // Detect debug break requests as soon as possible.
    339     reset_value = 10;
    340   }
    341   __ mov(r2, Operand(profiling_counter_));
    342   __ mov(r3, Operand(Smi::FromInt(reset_value)));
    343   __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
    344 }
    345 
    346 
    347 static const int kMaxBackEdgeWeight = 127;
    348 static const int kBackEdgeDistanceDivisor = 142;
    349 
    350 
    351 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt,
    352                                        Label* back_edge_target) {
    353   Comment cmnt(masm_, "[ Stack check");
    354   Label ok;
    355 
    356   if (FLAG_count_based_interrupts) {
    357     int weight = 1;
    358     if (FLAG_weighted_back_edges) {
    359       ASSERT(back_edge_target->is_bound());
    360       int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
    361       weight = Min(kMaxBackEdgeWeight,
    362                    Max(1, distance / kBackEdgeDistanceDivisor));
    363     }
    364     EmitProfilingCounterDecrement(weight);
    365     __ b(pl, &ok);
    366     InterruptStub stub;
    367     __ CallStub(&stub);
    368   } else {
    369     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
    370     __ cmp(sp, Operand(ip));
    371     __ b(hs, &ok);
    372     StackCheckStub stub;
    373     __ CallStub(&stub);
    374   }
    375 
    376   // Record a mapping of this PC offset to the OSR id.  This is used to find
    377   // the AST id from the unoptimized code in order to use it as a key into
    378   // the deoptimization input data found in the optimized code.
    379   RecordStackCheck(stmt->OsrEntryId());
    380 
    381   if (FLAG_count_based_interrupts) {
    382     EmitProfilingCounterReset();
    383   }
    384 
    385   __ bind(&ok);
    386   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
    387   // Record a mapping of the OSR id to this PC.  This is used if the OSR
    388   // entry becomes the target of a bailout.  We don't expect it to be, but
    389   // we want it to work if it is.
    390   PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
    391 }
    392 
    393 
    394 void FullCodeGenerator::EmitReturnSequence() {
    395   Comment cmnt(masm_, "[ Return sequence");
    396   if (return_label_.is_bound()) {
    397     __ b(&return_label_);
    398   } else {
    399     __ bind(&return_label_);
    400     if (FLAG_trace) {
    401       // Push the return value on the stack as the parameter.
    402       // Runtime::TraceExit returns its parameter in r0.
    403       __ push(r0);
    404       __ CallRuntime(Runtime::kTraceExit, 1);
    405     }
    406     if (FLAG_interrupt_at_exit || FLAG_self_optimization) {
    407       // Pretend that the exit is a backwards jump to the entry.
    408       int weight = 1;
    409       if (info_->ShouldSelfOptimize()) {
    410         weight = FLAG_interrupt_budget / FLAG_self_opt_count;
    411       } else if (FLAG_weighted_back_edges) {
    412         int distance = masm_->pc_offset();
    413         weight = Min(kMaxBackEdgeWeight,
    414                      Max(1, distance / kBackEdgeDistanceDivisor));
    415       }
    416       EmitProfilingCounterDecrement(weight);
    417       Label ok;
    418       __ b(pl, &ok);
    419       __ push(r0);
    420       if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
    421         __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
    422         __ push(r2);
    423         __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
    424       } else {
    425         InterruptStub stub;
    426         __ CallStub(&stub);
    427       }
    428       __ pop(r0);
    429       EmitProfilingCounterReset();
    430       __ bind(&ok);
    431     }
    432 
    433 #ifdef DEBUG
    434     // Add a label for checking the size of the code used for returning.
    435     Label check_exit_codesize;
    436     masm_->bind(&check_exit_codesize);
    437 #endif
    438     // Make sure that the constant pool is not emitted inside of the return
    439     // sequence.
    440     { Assembler::BlockConstPoolScope block_const_pool(masm_);
    441       // Here we use masm_-> instead of the __ macro to avoid the code coverage
    442       // tool from instrumenting as we rely on the code size here.
    443       int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
    444       CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
    445       __ RecordJSReturn();
    446       masm_->mov(sp, fp);
    447       masm_->ldm(ia_w, sp, fp.bit() | lr.bit());
    448       masm_->add(sp, sp, Operand(sp_delta));
    449       masm_->Jump(lr);
    450     }
    451 
    452 #ifdef DEBUG
    453     // Check that the size of the code used for returning is large enough
    454     // for the debugger's requirements.
    455     ASSERT(Assembler::kJSReturnSequenceInstructions <=
    456            masm_->InstructionsGeneratedSince(&check_exit_codesize));
    457 #endif
    458   }
    459 }
    460 
    461 
    462 void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
    463   ASSERT(var->IsStackAllocated() || var->IsContextSlot());
    464 }
    465 
    466 
    467 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
    468   ASSERT(var->IsStackAllocated() || var->IsContextSlot());
    469   codegen()->GetVar(result_register(), var);
    470 }
    471 
    472 
    473 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
    474   ASSERT(var->IsStackAllocated() || var->IsContextSlot());
    475   codegen()->GetVar(result_register(), var);
    476   __ push(result_register());
    477 }
    478 
    479 
    480 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
    481   ASSERT(var->IsStackAllocated() || var->IsContextSlot());
    482   // For simplicity we always test the accumulator register.
    483   codegen()->GetVar(result_register(), var);
    484   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
    485   codegen()->DoTest(this);
    486 }
    487 
    488 
    489 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
    490 }
    491 
    492 
    493 void FullCodeGenerator::AccumulatorValueContext::Plug(
    494     Heap::RootListIndex index) const {
    495   __ LoadRoot(result_register(), index);
    496 }
    497 
    498 
    499 void FullCodeGenerator::StackValueContext::Plug(
    500     Heap::RootListIndex index) const {
    501   __ LoadRoot(result_register(), index);
    502   __ push(result_register());
    503 }
    504 
    505 
    506 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
    507   codegen()->PrepareForBailoutBeforeSplit(condition(),
    508                                           true,
    509                                           true_label_,
    510                                           false_label_);
    511   if (index == Heap::kUndefinedValueRootIndex ||
    512       index == Heap::kNullValueRootIndex ||
    513       index == Heap::kFalseValueRootIndex) {
    514     if (false_label_ != fall_through_) __ b(false_label_);
    515   } else if (index == Heap::kTrueValueRootIndex) {
    516     if (true_label_ != fall_through_) __ b(true_label_);
    517   } else {
    518     __ LoadRoot(result_register(), index);
    519     codegen()->DoTest(this);
    520   }
    521 }
    522 
    523 
    524 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
    525 }
    526 
    527 
    528 void FullCodeGenerator::AccumulatorValueContext::Plug(
    529     Handle<Object> lit) const {
    530   __ mov(result_register(), Operand(lit));
    531 }
    532 
    533 
    534 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
    535   // Immediates cannot be pushed directly.
    536   __ mov(result_register(), Operand(lit));
    537   __ push(result_register());
    538 }
    539 
    540 
    541 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
    542   codegen()->PrepareForBailoutBeforeSplit(condition(),
    543                                           true,
    544                                           true_label_,
    545                                           false_label_);
    546   ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
    547   if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
    548     if (false_label_ != fall_through_) __ b(false_label_);
    549   } else if (lit->IsTrue() || lit->IsJSObject()) {
    550     if (true_label_ != fall_through_) __ b(true_label_);
    551   } else if (lit->IsString()) {
    552     if (String::cast(*lit)->length() == 0) {
    553       if (false_label_ != fall_through_) __ b(false_label_);
    554     } else {
    555       if (true_label_ != fall_through_) __ b(true_label_);
    556     }
    557   } else if (lit->IsSmi()) {
    558     if (Smi::cast(*lit)->value() == 0) {
    559       if (false_label_ != fall_through_) __ b(false_label_);
    560     } else {
    561       if (true_label_ != fall_through_) __ b(true_label_);
    562     }
    563   } else {
    564     // For simplicity we always test the accumulator register.
    565     __ mov(result_register(), Operand(lit));
    566     codegen()->DoTest(this);
    567   }
    568 }
    569 
    570 
    571 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
    572                                                    Register reg) const {
    573   ASSERT(count > 0);
    574   __ Drop(count);
    575 }
    576 
    577 
    578 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
    579     int count,
    580     Register reg) const {
    581   ASSERT(count > 0);
    582   __ Drop(count);
    583   __ Move(result_register(), reg);
    584 }
    585 
    586 
    587 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
    588                                                        Register reg) const {
    589   ASSERT(count > 0);
    590   if (count > 1) __ Drop(count - 1);
    591   __ str(reg, MemOperand(sp, 0));
    592 }
    593 
    594 
    595 void FullCodeGenerator::TestContext::DropAndPlug(int count,
    596                                                  Register reg) const {
    597   ASSERT(count > 0);
    598   // For simplicity we always test the accumulator register.
    599   __ Drop(count);
    600   __ Move(result_register(), reg);
    601   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
    602   codegen()->DoTest(this);
    603 }
    604 
    605 
    606 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
    607                                             Label* materialize_false) const {
    608   ASSERT(materialize_true == materialize_false);
    609   __ bind(materialize_true);
    610 }
    611 
    612 
    613 void FullCodeGenerator::AccumulatorValueContext::Plug(
    614     Label* materialize_true,
    615     Label* materialize_false) const {
    616   Label done;
    617   __ bind(materialize_true);
    618   __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
    619   __ jmp(&done);
    620   __ bind(materialize_false);
    621   __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
    622   __ bind(&done);
    623 }
    624 
    625 
    626 void FullCodeGenerator::StackValueContext::Plug(
    627     Label* materialize_true,
    628     Label* materialize_false) const {
    629   Label done;
    630   __ bind(materialize_true);
    631   __ LoadRoot(ip, Heap::kTrueValueRootIndex);
    632   __ push(ip);
    633   __ jmp(&done);
    634   __ bind(materialize_false);
    635   __ LoadRoot(ip, Heap::kFalseValueRootIndex);
    636   __ push(ip);
    637   __ bind(&done);
    638 }
    639 
    640 
    641 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
    642                                           Label* materialize_false) const {
    643   ASSERT(materialize_true == true_label_);
    644   ASSERT(materialize_false == false_label_);
    645 }
    646 
    647 
    648 void FullCodeGenerator::EffectContext::Plug(bool flag) const {
    649 }
    650 
    651 
    652 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
    653   Heap::RootListIndex value_root_index =
    654       flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
    655   __ LoadRoot(result_register(), value_root_index);
    656 }
    657 
    658 
    659 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
    660   Heap::RootListIndex value_root_index =
    661       flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
    662   __ LoadRoot(ip, value_root_index);
    663   __ push(ip);
    664 }
    665 
    666 
    667 void FullCodeGenerator::TestContext::Plug(bool flag) const {
    668   codegen()->PrepareForBailoutBeforeSplit(condition(),
    669                                           true,
    670                                           true_label_,
    671                                           false_label_);
    672   if (flag) {
    673     if (true_label_ != fall_through_) __ b(true_label_);
    674   } else {
    675     if (false_label_ != fall_through_) __ b(false_label_);
    676   }
    677 }
    678 
    679 
    680 void FullCodeGenerator::DoTest(Expression* condition,
    681                                Label* if_true,
    682                                Label* if_false,
    683                                Label* fall_through) {
    684   if (CpuFeatures::IsSupported(VFP3)) {
    685     ToBooleanStub stub(result_register());
    686     __ CallStub(&stub);
    687     __ tst(result_register(), result_register());
    688   } else {
    689     // Call the runtime to find the boolean value of the source and then
    690     // translate it into control flow to the pair of labels.
    691     __ push(result_register());
    692     __ CallRuntime(Runtime::kToBool, 1);
    693     __ LoadRoot(ip, Heap::kFalseValueRootIndex);
    694     __ cmp(r0, ip);
    695   }
    696   Split(ne, if_true, if_false, fall_through);
    697 }
    698 
    699 
    700 void FullCodeGenerator::Split(Condition cond,
    701                               Label* if_true,
    702                               Label* if_false,
    703                               Label* fall_through) {
    704   if (if_false == fall_through) {
    705     __ b(cond, if_true);
    706   } else if (if_true == fall_through) {
    707     __ b(NegateCondition(cond), if_false);
    708   } else {
    709     __ b(cond, if_true);
    710     __ b(if_false);
    711   }
    712 }
    713 
    714 
    715 MemOperand FullCodeGenerator::StackOperand(Variable* var) {
    716   ASSERT(var->IsStackAllocated());
    717   // Offset is negative because higher indexes are at lower addresses.
    718   int offset = -var->index() * kPointerSize;
    719   // Adjust by a (parameter or local) base offset.
    720   if (var->IsParameter()) {
    721     offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
    722   } else {
    723     offset += JavaScriptFrameConstants::kLocal0Offset;
    724   }
    725   return MemOperand(fp, offset);
    726 }
    727 
    728 
    729 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
    730   ASSERT(var->IsContextSlot() || var->IsStackAllocated());
    731   if (var->IsContextSlot()) {
    732     int context_chain_length = scope()->ContextChainLength(var->scope());
    733     __ LoadContext(scratch, context_chain_length);
    734     return ContextOperand(scratch, var->index());
    735   } else {
    736     return StackOperand(var);
    737   }
    738 }
    739 
    740 
    741 void FullCodeGenerator::GetVar(Register dest, Variable* var) {
    742   // Use destination as scratch.
    743   MemOperand location = VarOperand(var, dest);
    744   __ ldr(dest, location);
    745 }
    746 
    747 
    748 void FullCodeGenerator::SetVar(Variable* var,
    749                                Register src,
    750                                Register scratch0,
    751                                Register scratch1) {
    752   ASSERT(var->IsContextSlot() || var->IsStackAllocated());
    753   ASSERT(!scratch0.is(src));
    754   ASSERT(!scratch0.is(scratch1));
    755   ASSERT(!scratch1.is(src));
    756   MemOperand location = VarOperand(var, scratch0);
    757   __ str(src, location);
    758 
    759   // Emit the write barrier code if the location is in the heap.
    760   if (var->IsContextSlot()) {
    761     __ RecordWriteContextSlot(scratch0,
    762                               location.offset(),
    763                               src,
    764                               scratch1,
    765                               kLRHasBeenSaved,
    766                               kDontSaveFPRegs);
    767   }
    768 }
    769 
    770 
    771 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
    772                                                      bool should_normalize,
    773                                                      Label* if_true,
    774                                                      Label* if_false) {
    775   // Only prepare for bailouts before splits if we're in a test
    776   // context. Otherwise, we let the Visit function deal with the
    777   // preparation to avoid preparing with the same AST id twice.
    778   if (!context()->IsTest() || !info_->IsOptimizable()) return;
    779 
    780   Label skip;
    781   if (should_normalize) __ b(&skip);
    782   PrepareForBailout(expr, TOS_REG);
    783   if (should_normalize) {
    784     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
    785     __ cmp(r0, ip);
    786     Split(eq, if_true, if_false, NULL);
    787     __ bind(&skip);
    788   }
    789 }
    790 
    791 
    792 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
    793                                         VariableMode mode,
    794                                         FunctionLiteral* function) {
    795   // If it was not possible to allocate the variable at compile time, we
    796   // need to "declare" it at runtime to make sure it actually exists in the
    797   // local context.
    798   Variable* variable = proxy->var();
    799   bool binding_needs_init = (function == NULL) &&
    800       (mode == CONST || mode == CONST_HARMONY || mode == LET);
    801   switch (variable->location()) {
    802     case Variable::UNALLOCATED:
    803       ++global_count_;
    804       break;
    805 
    806     case Variable::PARAMETER:
    807     case Variable::LOCAL:
    808       if (function != NULL) {
    809         Comment cmnt(masm_, "[ Declaration");
    810         VisitForAccumulatorValue(function);
    811         __ str(result_register(), StackOperand(variable));
    812       } else if (binding_needs_init) {
    813         Comment cmnt(masm_, "[ Declaration");
    814         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
    815         __ str(ip, StackOperand(variable));
    816       }
    817       break;
    818 
    819     case Variable::CONTEXT:
    820       // The variable in the decl always resides in the current function
    821       // context.
    822       ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
    823       if (FLAG_debug_code) {
    824         // Check that we're not inside a with or catch context.
    825         __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset));
    826         __ CompareRoot(r1, Heap::kWithContextMapRootIndex);
    827         __ Check(ne, "Declaration in with context.");
    828         __ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
    829         __ Check(ne, "Declaration in catch context.");
    830       }
    831       if (function != NULL) {
    832         Comment cmnt(masm_, "[ Declaration");
    833         VisitForAccumulatorValue(function);
    834         __ str(result_register(), ContextOperand(cp, variable->index()));
    835         int offset = Context::SlotOffset(variable->index());
    836         // We know that we have written a function, which is not a smi.
    837         __ RecordWriteContextSlot(cp,
    838                                   offset,
    839                                   result_register(),
    840                                   r2,
    841                                   kLRHasBeenSaved,
    842                                   kDontSaveFPRegs,
    843                                   EMIT_REMEMBERED_SET,
    844                                   OMIT_SMI_CHECK);
    845         PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
    846       } else if (binding_needs_init) {
    847         Comment cmnt(masm_, "[ Declaration");
    848         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
    849         __ str(ip, ContextOperand(cp, variable->index()));
    850         // No write barrier since the_hole_value is in old space.
    851         PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
    852       }
    853       break;
    854 
    855     case Variable::LOOKUP: {
    856       Comment cmnt(masm_, "[ Declaration");
    857       __ mov(r2, Operand(variable->name()));
    858       // Declaration nodes are always introduced in one of four modes.
    859       ASSERT(mode == VAR ||
    860              mode == CONST ||
    861              mode == CONST_HARMONY ||
    862              mode == LET);
    863       PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY)
    864           ? READ_ONLY : NONE;
    865       __ mov(r1, Operand(Smi::FromInt(attr)));
    866       // Push initial value, if any.
    867       // Note: For variables we must not push an initial value (such as
    868       // 'undefined') because we may have a (legal) redeclaration and we
    869       // must not destroy the current value.
    870       if (function != NULL) {
    871         __ Push(cp, r2, r1);
    872         // Push initial value for function declaration.
    873         VisitForStackValue(function);
    874       } else if (binding_needs_init) {
    875         __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
    876         __ Push(cp, r2, r1, r0);
    877       } else {
    878         __ mov(r0, Operand(Smi::FromInt(0)));  // Indicates no initial value.
    879         __ Push(cp, r2, r1, r0);
    880       }
    881       __ CallRuntime(Runtime::kDeclareContextSlot, 4);
    882       break;
    883     }
    884   }
    885 }
    886 
    887 
    888 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
    889   // Call the runtime to declare the globals.
    890   // The context is the first argument.
    891   __ mov(r1, Operand(pairs));
    892   __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
    893   __ Push(cp, r1, r0);
    894   __ CallRuntime(Runtime::kDeclareGlobals, 3);
    895   // Return value is ignored.
    896 }
    897 
    898 
    899 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
    900   Comment cmnt(masm_, "[ SwitchStatement");
    901   Breakable nested_statement(this, stmt);
    902   SetStatementPosition(stmt);
    903 
    904   // Keep the switch value on the stack until a case matches.
    905   VisitForStackValue(stmt->tag());
    906   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
    907 
    908   ZoneList<CaseClause*>* clauses = stmt->cases();
    909   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
    910 
    911   Label next_test;  // Recycled for each test.
    912   // Compile all the tests with branches to their bodies.
    913   for (int i = 0; i < clauses->length(); i++) {
    914     CaseClause* clause = clauses->at(i);
    915     clause->body_target()->Unuse();
    916 
    917     // The default is not a test, but remember it as final fall through.
    918     if (clause->is_default()) {
    919       default_clause = clause;
    920       continue;
    921     }
    922 
    923     Comment cmnt(masm_, "[ Case comparison");
    924     __ bind(&next_test);
    925     next_test.Unuse();
    926 
    927     // Compile the label expression.
    928     VisitForAccumulatorValue(clause->label());
    929 
    930     // Perform the comparison as if via '==='.
    931     __ ldr(r1, MemOperand(sp, 0));  // Switch value.
    932     bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
    933     JumpPatchSite patch_site(masm_);
    934     if (inline_smi_code) {
    935       Label slow_case;
    936       __ orr(r2, r1, r0);
    937       patch_site.EmitJumpIfNotSmi(r2, &slow_case);
    938 
    939       __ cmp(r1, r0);
    940       __ b(ne, &next_test);
    941       __ Drop(1);  // Switch value is no longer needed.
    942       __ b(clause->body_target());
    943       __ bind(&slow_case);
    944     }
    945 
    946     // Record position before stub call for type feedback.
    947     SetSourcePosition(clause->position());
    948     Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
    949     CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
    950     patch_site.EmitPatchInfo();
    951 
    952     __ cmp(r0, Operand(0));
    953     __ b(ne, &next_test);
    954     __ Drop(1);  // Switch value is no longer needed.
    955     __ b(clause->body_target());
    956   }
    957 
    958   // Discard the test value and jump to the default if present, otherwise to
    959   // the end of the statement.
    960   __ bind(&next_test);
    961   __ Drop(1);  // Switch value is no longer needed.
    962   if (default_clause == NULL) {
    963     __ b(nested_statement.break_label());
    964   } else {
    965     __ b(default_clause->body_target());
    966   }
    967 
    968   // Compile all the case bodies.
    969   for (int i = 0; i < clauses->length(); i++) {
    970     Comment cmnt(masm_, "[ Case body");
    971     CaseClause* clause = clauses->at(i);
    972     __ bind(clause->body_target());
    973     PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
    974     VisitStatements(clause->statements());
    975   }
    976 
    977   __ bind(nested_statement.break_label());
    978   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
    979 }
    980 
    981 
    982 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
    983   Comment cmnt(masm_, "[ ForInStatement");
    984   SetStatementPosition(stmt);
    985 
    986   Label loop, exit;
    987   ForIn loop_statement(this, stmt);
    988   increment_loop_depth();
    989 
    990   // Get the object to enumerate over. Both SpiderMonkey and JSC
    991   // ignore null and undefined in contrast to the specification; see
    992   // ECMA-262 section 12.6.4.
    993   VisitForAccumulatorValue(stmt->enumerable());
    994   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
    995   __ cmp(r0, ip);
    996   __ b(eq, &exit);
    997   Register null_value = r5;
    998   __ LoadRoot(null_value, Heap::kNullValueRootIndex);
    999   __ cmp(r0, null_value);
   1000   __ b(eq, &exit);
   1001 
   1002   PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
   1003 
   1004   // Convert the object to a JS object.
   1005   Label convert, done_convert;
   1006   __ JumpIfSmi(r0, &convert);
   1007   __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
   1008   __ b(ge, &done_convert);
   1009   __ bind(&convert);
   1010   __ push(r0);
   1011   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
   1012   __ bind(&done_convert);
   1013   __ push(r0);
   1014 
   1015   // Check for proxies.
   1016   Label call_runtime;
   1017   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
   1018   __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
   1019   __ b(le, &call_runtime);
   1020 
   1021   // Check cache validity in generated code. This is a fast case for
   1022   // the JSObject::IsSimpleEnum cache validity checks. If we cannot
   1023   // guarantee cache validity, call the runtime system to check cache
   1024   // validity or get the property names in a fixed array.
   1025   __ CheckEnumCache(null_value, &call_runtime);
   1026 
   1027   // The enum cache is valid.  Load the map of the object being
   1028   // iterated over and use the cache for the iteration.
   1029   Label use_cache;
   1030   __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
   1031   __ b(&use_cache);
   1032 
   1033   // Get the set of properties to enumerate.
   1034   __ bind(&call_runtime);
   1035   __ push(r0);  // Duplicate the enumerable object on the stack.
   1036   __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
   1037 
   1038   // If we got a map from the runtime call, we can do a fast
   1039   // modification check. Otherwise, we got a fixed array, and we have
   1040   // to do a slow check.
   1041   Label fixed_array;
   1042   __ mov(r2, r0);
   1043   __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
   1044   __ LoadRoot(ip, Heap::kMetaMapRootIndex);
   1045   __ cmp(r1, ip);
   1046   __ b(ne, &fixed_array);
   1047 
   1048   // We got a map in register r0. Get the enumeration cache from it.
   1049   __ bind(&use_cache);
   1050   __ LoadInstanceDescriptors(r0, r1);
   1051   __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
   1052   __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
   1053 
   1054   // Set up the four remaining stack slots.
   1055   __ push(r0);  // Map.
   1056   __ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset));
   1057   __ mov(r0, Operand(Smi::FromInt(0)));
   1058   // Push enumeration cache, enumeration cache length (as smi) and zero.
   1059   __ Push(r2, r1, r0);
   1060   __ jmp(&loop);
   1061 
   1062   // We got a fixed array in register r0. Iterate through that.
   1063   Label non_proxy;
   1064   __ bind(&fixed_array);
   1065 
   1066   Handle<JSGlobalPropertyCell> cell =
   1067       isolate()->factory()->NewJSGlobalPropertyCell(
   1068           Handle<Object>(
   1069               Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker)));
   1070   RecordTypeFeedbackCell(stmt->PrepareId(), cell);
   1071   __ LoadHeapObject(r1, cell);
   1072   __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
   1073   __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset));
   1074 
   1075   __ mov(r1, Operand(Smi::FromInt(1)));  // Smi indicates slow check
   1076   __ ldr(r2, MemOperand(sp, 0 * kPointerSize));  // Get enumerated object
   1077   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
   1078   __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE);
   1079   __ b(gt, &non_proxy);
   1080   __ mov(r1, Operand(Smi::FromInt(0)));  // Zero indicates proxy
   1081   __ bind(&non_proxy);
   1082   __ Push(r1, r0);  // Smi and array
   1083   __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
   1084   __ mov(r0, Operand(Smi::FromInt(0)));
   1085   __ Push(r1, r0);  // Fixed array length (as smi) and initial index.
   1086 
   1087   // Generate code for doing the condition check.
   1088   PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
   1089   __ bind(&loop);
   1090   // Load the current count to r0, load the length to r1.
   1091   __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
   1092   __ cmp(r0, r1);  // Compare to the array length.
   1093   __ b(hs, loop_statement.break_label());
   1094 
   1095   // Get the current entry of the array into register r3.
   1096   __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
   1097   __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   1098   __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
   1099 
   1100   // Get the expected map from the stack or a smi in the
   1101   // permanent slow case into register r2.
   1102   __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
   1103 
   1104   // Check if the expected map still matches that of the enumerable.
   1105   // If not, we may have to filter the key.
   1106   Label update_each;
   1107   __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
   1108   __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
   1109   __ cmp(r4, Operand(r2));
   1110   __ b(eq, &update_each);
   1111 
   1112   // For proxies, no filtering is done.
   1113   // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
   1114   __ cmp(r2, Operand(Smi::FromInt(0)));
   1115   __ b(eq, &update_each);
   1116 
   1117   // Convert the entry to a string or (smi) 0 if it isn't a property
   1118   // any more. If the property has been removed while iterating, we
   1119   // just skip it.
   1120   __ push(r1);  // Enumerable.
   1121   __ push(r3);  // Current entry.
   1122   __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
   1123   __ mov(r3, Operand(r0), SetCC);
   1124   __ b(eq, loop_statement.continue_label());
   1125 
   1126   // Update the 'each' property or variable from the possibly filtered
   1127   // entry in register r3.
   1128   __ bind(&update_each);
   1129   __ mov(result_register(), r3);
   1130   // Perform the assignment as if via '='.
   1131   { EffectContext context(this);
   1132     EmitAssignment(stmt->each());
   1133   }
   1134 
   1135   // Generate code for the body of the loop.
   1136   Visit(stmt->body());
   1137 
   1138   // Generate code for the going to the next element by incrementing
   1139   // the index (smi) stored on top of the stack.
   1140   __ bind(loop_statement.continue_label());
   1141   __ pop(r0);
   1142   __ add(r0, r0, Operand(Smi::FromInt(1)));
   1143   __ push(r0);
   1144 
   1145   EmitStackCheck(stmt, &loop);
   1146   __ b(&loop);
   1147 
   1148   // Remove the pointers stored on the stack.
   1149   __ bind(loop_statement.break_label());
   1150   __ Drop(5);
   1151 
   1152   // Exit and decrement the loop depth.
   1153   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
   1154   __ bind(&exit);
   1155   decrement_loop_depth();
   1156 }
   1157 
   1158 
   1159 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
   1160                                        bool pretenure) {
   1161   // Use the fast case closure allocation code that allocates in new
   1162   // space for nested functions that don't need literals cloning. If
   1163   // we're running with the --always-opt or the --prepare-always-opt
   1164   // flag, we need to use the runtime function so that the new function
   1165   // we are creating here gets a chance to have its code optimized and
   1166   // doesn't just get a copy of the existing unoptimized code.
   1167   if (!FLAG_always_opt &&
   1168       !FLAG_prepare_always_opt &&
   1169       !pretenure &&
   1170       scope()->is_function_scope() &&
   1171       info->num_literals() == 0) {
   1172     FastNewClosureStub stub(info->language_mode());
   1173     __ mov(r0, Operand(info));
   1174     __ push(r0);
   1175     __ CallStub(&stub);
   1176   } else {
   1177     __ mov(r0, Operand(info));
   1178     __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex
   1179                               : Heap::kFalseValueRootIndex);
   1180     __ Push(cp, r0, r1);
   1181     __ CallRuntime(Runtime::kNewClosure, 3);
   1182   }
   1183   context()->Plug(r0);
   1184 }
   1185 
   1186 
   1187 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
   1188   Comment cmnt(masm_, "[ VariableProxy");
   1189   EmitVariableLoad(expr);
   1190 }
   1191 
   1192 
   1193 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
   1194                                                       TypeofState typeof_state,
   1195                                                       Label* slow) {
   1196   Register current = cp;
   1197   Register next = r1;
   1198   Register temp = r2;
   1199 
   1200   Scope* s = scope();
   1201   while (s != NULL) {
   1202     if (s->num_heap_slots() > 0) {
   1203       if (s->calls_non_strict_eval()) {
   1204         // Check that extension is NULL.
   1205         __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
   1206         __ tst(temp, temp);
   1207         __ b(ne, slow);
   1208       }
   1209       // Load next context in chain.
   1210       __ ldr(next, ContextOperand(current, Context::PREVIOUS_INDEX));
   1211       // Walk the rest of the chain without clobbering cp.
   1212       current = next;
   1213     }
   1214     // If no outer scope calls eval, we do not need to check more
   1215     // context extensions.
   1216     if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
   1217     s = s->outer_scope();
   1218   }
   1219 
   1220   if (s->is_eval_scope()) {
   1221     Label loop, fast;
   1222     if (!current.is(next)) {
   1223       __ Move(next, current);
   1224     }
   1225     __ bind(&loop);
   1226     // Terminate at global context.
   1227     __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset));
   1228     __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex);
   1229     __ cmp(temp, ip);
   1230     __ b(eq, &fast);
   1231     // Check that extension is NULL.
   1232     __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX));
   1233     __ tst(temp, temp);
   1234     __ b(ne, slow);
   1235     // Load next context in chain.
   1236     __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX));
   1237     __ b(&loop);
   1238     __ bind(&fast);
   1239   }
   1240 
   1241   __ ldr(r0, GlobalObjectOperand());
   1242   __ mov(r2, Operand(var->name()));
   1243   RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
   1244       ? RelocInfo::CODE_TARGET
   1245       : RelocInfo::CODE_TARGET_CONTEXT;
   1246   Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   1247   CallIC(ic, mode);
   1248 }
   1249 
   1250 
   1251 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
   1252                                                                 Label* slow) {
   1253   ASSERT(var->IsContextSlot());
   1254   Register context = cp;
   1255   Register next = r3;
   1256   Register temp = r4;
   1257 
   1258   for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
   1259     if (s->num_heap_slots() > 0) {
   1260       if (s->calls_non_strict_eval()) {
   1261         // Check that extension is NULL.
   1262         __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
   1263         __ tst(temp, temp);
   1264         __ b(ne, slow);
   1265       }
   1266       __ ldr(next, ContextOperand(context, Context::PREVIOUS_INDEX));
   1267       // Walk the rest of the chain without clobbering cp.
   1268       context = next;
   1269     }
   1270   }
   1271   // Check that last extension is NULL.
   1272   __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
   1273   __ tst(temp, temp);
   1274   __ b(ne, slow);
   1275 
   1276   // This function is used only for loads, not stores, so it's safe to
   1277   // return an cp-based operand (the write barrier cannot be allowed to
   1278   // destroy the cp register).
   1279   return ContextOperand(context, var->index());
   1280 }
   1281 
   1282 
   1283 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
   1284                                                   TypeofState typeof_state,
   1285                                                   Label* slow,
   1286                                                   Label* done) {
   1287   // Generate fast-case code for variables that might be shadowed by
   1288   // eval-introduced variables.  Eval is used a lot without
   1289   // introducing variables.  In those cases, we do not want to
   1290   // perform a runtime call for all variables in the scope
   1291   // containing the eval.
   1292   if (var->mode() == DYNAMIC_GLOBAL) {
   1293     EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
   1294     __ jmp(done);
   1295   } else if (var->mode() == DYNAMIC_LOCAL) {
   1296     Variable* local = var->local_if_not_shadowed();
   1297     __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
   1298     if (local->mode() == CONST ||
   1299         local->mode() == CONST_HARMONY ||
   1300         local->mode() == LET) {
   1301       __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
   1302       if (local->mode() == CONST) {
   1303         __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
   1304       } else {  // LET || CONST_HARMONY
   1305         __ b(ne, done);
   1306         __ mov(r0, Operand(var->name()));
   1307         __ push(r0);
   1308         __ CallRuntime(Runtime::kThrowReferenceError, 1);
   1309       }
   1310     }
   1311     __ jmp(done);
   1312   }
   1313 }
   1314 
   1315 
   1316 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
   1317   // Record position before possible IC call.
   1318   SetSourcePosition(proxy->position());
   1319   Variable* var = proxy->var();
   1320 
   1321   // Three cases: global variables, lookup variables, and all other types of
   1322   // variables.
   1323   switch (var->location()) {
   1324     case Variable::UNALLOCATED: {
   1325       Comment cmnt(masm_, "Global variable");
   1326       // Use inline caching. Variable name is passed in r2 and the global
   1327       // object (receiver) in r0.
   1328       __ ldr(r0, GlobalObjectOperand());
   1329       __ mov(r2, Operand(var->name()));
   1330       Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   1331       CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
   1332       context()->Plug(r0);
   1333       break;
   1334     }
   1335 
   1336     case Variable::PARAMETER:
   1337     case Variable::LOCAL:
   1338     case Variable::CONTEXT: {
   1339       Comment cmnt(masm_, var->IsContextSlot()
   1340                               ? "Context variable"
   1341                               : "Stack variable");
   1342       if (var->binding_needs_init()) {
   1343         // var->scope() may be NULL when the proxy is located in eval code and
   1344         // refers to a potential outside binding. Currently those bindings are
   1345         // always looked up dynamically, i.e. in that case
   1346         //     var->location() == LOOKUP.
   1347         // always holds.
   1348         ASSERT(var->scope() != NULL);
   1349 
   1350         // Check if the binding really needs an initialization check. The check
   1351         // can be skipped in the following situation: we have a LET or CONST
   1352         // binding in harmony mode, both the Variable and the VariableProxy have
   1353         // the same declaration scope (i.e. they are both in global code, in the
   1354         // same function or in the same eval code) and the VariableProxy is in
   1355         // the source physically located after the initializer of the variable.
   1356         //
   1357         // We cannot skip any initialization checks for CONST in non-harmony
   1358         // mode because const variables may be declared but never initialized:
   1359         //   if (false) { const x; }; var y = x;
   1360         //
   1361         // The condition on the declaration scopes is a conservative check for
   1362         // nested functions that access a binding and are called before the
   1363         // binding is initialized:
   1364         //   function() { f(); let x = 1; function f() { x = 2; } }
   1365         //
   1366         bool skip_init_check;
   1367         if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
   1368           skip_init_check = false;
   1369         } else {
   1370           // Check that we always have valid source position.
   1371           ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
   1372           ASSERT(proxy->position() != RelocInfo::kNoPosition);
   1373           skip_init_check = var->mode() != CONST &&
   1374               var->initializer_position() < proxy->position();
   1375         }
   1376 
   1377         if (!skip_init_check) {
   1378           // Let and const need a read barrier.
   1379           GetVar(r0, var);
   1380           __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
   1381           if (var->mode() == LET || var->mode() == CONST_HARMONY) {
   1382             // Throw a reference error when using an uninitialized let/const
   1383             // binding in harmony mode.
   1384             Label done;
   1385             __ b(ne, &done);
   1386             __ mov(r0, Operand(var->name()));
   1387             __ push(r0);
   1388             __ CallRuntime(Runtime::kThrowReferenceError, 1);
   1389             __ bind(&done);
   1390           } else {
   1391             // Uninitalized const bindings outside of harmony mode are unholed.
   1392             ASSERT(var->mode() == CONST);
   1393             __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
   1394           }
   1395           context()->Plug(r0);
   1396           break;
   1397         }
   1398       }
   1399       context()->Plug(var);
   1400       break;
   1401     }
   1402 
   1403     case Variable::LOOKUP: {
   1404       Label done, slow;
   1405       // Generate code for loading from variables potentially shadowed
   1406       // by eval-introduced variables.
   1407       EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
   1408       __ bind(&slow);
   1409       Comment cmnt(masm_, "Lookup variable");
   1410       __ mov(r1, Operand(var->name()));
   1411       __ Push(cp, r1);  // Context and name.
   1412       __ CallRuntime(Runtime::kLoadContextSlot, 2);
   1413       __ bind(&done);
   1414       context()->Plug(r0);
   1415     }
   1416   }
   1417 }
   1418 
   1419 
   1420 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   1421   Comment cmnt(masm_, "[ RegExpLiteral");
   1422   Label materialized;
   1423   // Registers will be used as follows:
   1424   // r5 = materialized value (RegExp literal)
   1425   // r4 = JS function, literals array
   1426   // r3 = literal index
   1427   // r2 = RegExp pattern
   1428   // r1 = RegExp flags
   1429   // r0 = RegExp literal clone
   1430   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   1431   __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
   1432   int literal_offset =
   1433       FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
   1434   __ ldr(r5, FieldMemOperand(r4, literal_offset));
   1435   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   1436   __ cmp(r5, ip);
   1437   __ b(ne, &materialized);
   1438 
   1439   // Create regexp literal using runtime function.
   1440   // Result will be in r0.
   1441   __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
   1442   __ mov(r2, Operand(expr->pattern()));
   1443   __ mov(r1, Operand(expr->flags()));
   1444   __ Push(r4, r3, r2, r1);
   1445   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   1446   __ mov(r5, r0);
   1447 
   1448   __ bind(&materialized);
   1449   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
   1450   Label allocated, runtime_allocate;
   1451   __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
   1452   __ jmp(&allocated);
   1453 
   1454   __ bind(&runtime_allocate);
   1455   __ push(r5);
   1456   __ mov(r0, Operand(Smi::FromInt(size)));
   1457   __ push(r0);
   1458   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
   1459   __ pop(r5);
   1460 
   1461   __ bind(&allocated);
   1462   // After this, registers are used as follows:
   1463   // r0: Newly allocated regexp.
   1464   // r5: Materialized regexp.
   1465   // r2: temp.
   1466   __ CopyFields(r0, r5, r2.bit(), size / kPointerSize);
   1467   context()->Plug(r0);
   1468 }
   1469 
   1470 
   1471 void FullCodeGenerator::EmitAccessor(Expression* expression) {
   1472   if (expression == NULL) {
   1473     __ LoadRoot(r1, Heap::kNullValueRootIndex);
   1474     __ push(r1);
   1475   } else {
   1476     VisitForStackValue(expression);
   1477   }
   1478 }
   1479 
   1480 
   1481 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   1482   Comment cmnt(masm_, "[ ObjectLiteral");
   1483   Handle<FixedArray> constant_properties = expr->constant_properties();
   1484   __ ldr(r3, MemOperand(fp,  JavaScriptFrameConstants::kFunctionOffset));
   1485   __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
   1486   __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
   1487   __ mov(r1, Operand(constant_properties));
   1488   int flags = expr->fast_elements()
   1489       ? ObjectLiteral::kFastElements
   1490       : ObjectLiteral::kNoFlags;
   1491   flags |= expr->has_function()
   1492       ? ObjectLiteral::kHasFunction
   1493       : ObjectLiteral::kNoFlags;
   1494   __ mov(r0, Operand(Smi::FromInt(flags)));
   1495   __ Push(r3, r2, r1, r0);
   1496   int properties_count = constant_properties->length() / 2;
   1497   if (expr->depth() > 1) {
   1498     __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
   1499   } else if (flags != ObjectLiteral::kFastElements ||
   1500       properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
   1501     __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
   1502   } else {
   1503     FastCloneShallowObjectStub stub(properties_count);
   1504     __ CallStub(&stub);
   1505   }
   1506 
   1507   // If result_saved is true the result is on top of the stack.  If
   1508   // result_saved is false the result is in r0.
   1509   bool result_saved = false;
   1510 
   1511   // Mark all computed expressions that are bound to a key that
   1512   // is shadowed by a later occurrence of the same key. For the
   1513   // marked expressions, no store code is emitted.
   1514   expr->CalculateEmitStore();
   1515 
   1516   AccessorTable accessor_table(isolate()->zone());
   1517   for (int i = 0; i < expr->properties()->length(); i++) {
   1518     ObjectLiteral::Property* property = expr->properties()->at(i);
   1519     if (property->IsCompileTimeValue()) continue;
   1520 
   1521     Literal* key = property->key();
   1522     Expression* value = property->value();
   1523     if (!result_saved) {
   1524       __ push(r0);  // Save result on stack
   1525       result_saved = true;
   1526     }
   1527     switch (property->kind()) {
   1528       case ObjectLiteral::Property::CONSTANT:
   1529         UNREACHABLE();
   1530       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   1531         ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
   1532         // Fall through.
   1533       case ObjectLiteral::Property::COMPUTED:
   1534         if (key->handle()->IsSymbol()) {
   1535           if (property->emit_store()) {
   1536             VisitForAccumulatorValue(value);
   1537             __ mov(r2, Operand(key->handle()));
   1538             __ ldr(r1, MemOperand(sp));
   1539             Handle<Code> ic = is_classic_mode()
   1540                 ? isolate()->builtins()->StoreIC_Initialize()
   1541                 : isolate()->builtins()->StoreIC_Initialize_Strict();
   1542             CallIC(ic, RelocInfo::CODE_TARGET, key->id());
   1543             PrepareForBailoutForId(key->id(), NO_REGISTERS);
   1544           } else {
   1545             VisitForEffect(value);
   1546           }
   1547           break;
   1548         }
   1549         // Fall through.
   1550       case ObjectLiteral::Property::PROTOTYPE:
   1551         // Duplicate receiver on stack.
   1552         __ ldr(r0, MemOperand(sp));
   1553         __ push(r0);
   1554         VisitForStackValue(key);
   1555         VisitForStackValue(value);
   1556         if (property->emit_store()) {
   1557           __ mov(r0, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
   1558           __ push(r0);
   1559           __ CallRuntime(Runtime::kSetProperty, 4);
   1560         } else {
   1561           __ Drop(3);
   1562         }
   1563         break;
   1564       case ObjectLiteral::Property::GETTER:
   1565         accessor_table.lookup(key)->second->getter = value;
   1566         break;
   1567       case ObjectLiteral::Property::SETTER:
   1568         accessor_table.lookup(key)->second->setter = value;
   1569         break;
   1570     }
   1571   }
   1572 
   1573   // Emit code to define accessors, using only a single call to the runtime for
   1574   // each pair of corresponding getters and setters.
   1575   for (AccessorTable::Iterator it = accessor_table.begin();
   1576        it != accessor_table.end();
   1577        ++it) {
   1578     __ ldr(r0, MemOperand(sp));  // Duplicate receiver.
   1579     __ push(r0);
   1580     VisitForStackValue(it->first);
   1581     EmitAccessor(it->second->getter);
   1582     EmitAccessor(it->second->setter);
   1583     __ mov(r0, Operand(Smi::FromInt(NONE)));
   1584     __ push(r0);
   1585     __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
   1586   }
   1587 
   1588   if (expr->has_function()) {
   1589     ASSERT(result_saved);
   1590     __ ldr(r0, MemOperand(sp));
   1591     __ push(r0);
   1592     __ CallRuntime(Runtime::kToFastProperties, 1);
   1593   }
   1594 
   1595   if (result_saved) {
   1596     context()->PlugTOS();
   1597   } else {
   1598     context()->Plug(r0);
   1599   }
   1600 }
   1601 
   1602 
   1603 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
   1604   Comment cmnt(masm_, "[ ArrayLiteral");
   1605 
   1606   ZoneList<Expression*>* subexprs = expr->values();
   1607   int length = subexprs->length();
   1608   Handle<FixedArray> constant_elements = expr->constant_elements();
   1609   ASSERT_EQ(2, constant_elements->length());
   1610   ElementsKind constant_elements_kind =
   1611       static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
   1612   bool has_fast_elements = constant_elements_kind == FAST_ELEMENTS;
   1613   Handle<FixedArrayBase> constant_elements_values(
   1614       FixedArrayBase::cast(constant_elements->get(1)));
   1615 
   1616   __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   1617   __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
   1618   __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
   1619   __ mov(r1, Operand(constant_elements));
   1620   __ Push(r3, r2, r1);
   1621   if (has_fast_elements && constant_elements_values->map() ==
   1622       isolate()->heap()->fixed_cow_array_map()) {
   1623     FastCloneShallowArrayStub stub(
   1624         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
   1625     __ CallStub(&stub);
   1626     __ IncrementCounter(
   1627         isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
   1628   } else if (expr->depth() > 1) {
   1629     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
   1630   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
   1631     __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
   1632   } else {
   1633     ASSERT(constant_elements_kind == FAST_ELEMENTS ||
   1634            constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
   1635            FLAG_smi_only_arrays);
   1636     FastCloneShallowArrayStub::Mode mode = has_fast_elements
   1637       ? FastCloneShallowArrayStub::CLONE_ELEMENTS
   1638       : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
   1639     FastCloneShallowArrayStub stub(mode, length);
   1640     __ CallStub(&stub);
   1641   }
   1642 
   1643   bool result_saved = false;  // Is the result saved to the stack?
   1644 
   1645   // Emit code to evaluate all the non-constant subexpressions and to store
   1646   // them into the newly cloned array.
   1647   for (int i = 0; i < length; i++) {
   1648     Expression* subexpr = subexprs->at(i);
   1649     // If the subexpression is a literal or a simple materialized literal it
   1650     // is already set in the cloned array.
   1651     if (subexpr->AsLiteral() != NULL ||
   1652         CompileTimeValue::IsCompileTimeValue(subexpr)) {
   1653       continue;
   1654     }
   1655 
   1656     if (!result_saved) {
   1657       __ push(r0);
   1658       result_saved = true;
   1659     }
   1660     VisitForAccumulatorValue(subexpr);
   1661 
   1662     if (constant_elements_kind == FAST_ELEMENTS) {
   1663       int offset = FixedArray::kHeaderSize + (i * kPointerSize);
   1664       __ ldr(r6, MemOperand(sp));  // Copy of array literal.
   1665       __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
   1666       __ str(result_register(), FieldMemOperand(r1, offset));
   1667       // Update the write barrier for the array store.
   1668       __ RecordWriteField(r1, offset, result_register(), r2,
   1669                           kLRHasBeenSaved, kDontSaveFPRegs,
   1670                           EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
   1671     } else {
   1672       __ ldr(r1, MemOperand(sp));  // Copy of array literal.
   1673       __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset));
   1674       __ mov(r3, Operand(Smi::FromInt(i)));
   1675       __ mov(r4, Operand(Smi::FromInt(expr->literal_index())));
   1676       StoreArrayLiteralElementStub stub;
   1677       __ CallStub(&stub);
   1678     }
   1679 
   1680     PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
   1681   }
   1682 
   1683   if (result_saved) {
   1684     context()->PlugTOS();
   1685   } else {
   1686     context()->Plug(r0);
   1687   }
   1688 }
   1689 
   1690 
   1691 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
   1692   Comment cmnt(masm_, "[ Assignment");
   1693   // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
   1694   // on the left-hand side.
   1695   if (!expr->target()->IsValidLeftHandSide()) {
   1696     VisitForEffect(expr->target());
   1697     return;
   1698   }
   1699 
   1700   // Left-hand side can only be a property, a global or a (parameter or local)
   1701   // slot.
   1702   enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
   1703   LhsKind assign_type = VARIABLE;
   1704   Property* property = expr->target()->AsProperty();
   1705   if (property != NULL) {
   1706     assign_type = (property->key()->IsPropertyName())
   1707         ? NAMED_PROPERTY
   1708         : KEYED_PROPERTY;
   1709   }
   1710 
   1711   // Evaluate LHS expression.
   1712   switch (assign_type) {
   1713     case VARIABLE:
   1714       // Nothing to do here.
   1715       break;
   1716     case NAMED_PROPERTY:
   1717       if (expr->is_compound()) {
   1718         // We need the receiver both on the stack and in the accumulator.
   1719         VisitForAccumulatorValue(property->obj());
   1720         __ push(result_register());
   1721       } else {
   1722         VisitForStackValue(property->obj());
   1723       }
   1724       break;
   1725     case KEYED_PROPERTY:
   1726       if (expr->is_compound()) {
   1727         VisitForStackValue(property->obj());
   1728         VisitForAccumulatorValue(property->key());
   1729         __ ldr(r1, MemOperand(sp, 0));
   1730         __ push(r0);
   1731       } else {
   1732         VisitForStackValue(property->obj());
   1733         VisitForStackValue(property->key());
   1734       }
   1735       break;
   1736   }
   1737 
   1738   // For compound assignments we need another deoptimization point after the
   1739   // variable/property load.
   1740   if (expr->is_compound()) {
   1741     { AccumulatorValueContext context(this);
   1742       switch (assign_type) {
   1743         case VARIABLE:
   1744           EmitVariableLoad(expr->target()->AsVariableProxy());
   1745           PrepareForBailout(expr->target(), TOS_REG);
   1746           break;
   1747         case NAMED_PROPERTY:
   1748           EmitNamedPropertyLoad(property);
   1749           PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
   1750           break;
   1751         case KEYED_PROPERTY:
   1752           EmitKeyedPropertyLoad(property);
   1753           PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
   1754           break;
   1755       }
   1756     }
   1757 
   1758     Token::Value op = expr->binary_op();
   1759     __ push(r0);  // Left operand goes on the stack.
   1760     VisitForAccumulatorValue(expr->value());
   1761 
   1762     OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
   1763         ? OVERWRITE_RIGHT
   1764         : NO_OVERWRITE;
   1765     SetSourcePosition(expr->position() + 1);
   1766     AccumulatorValueContext context(this);
   1767     if (ShouldInlineSmiCase(op)) {
   1768       EmitInlineSmiBinaryOp(expr->binary_operation(),
   1769                             op,
   1770                             mode,
   1771                             expr->target(),
   1772                             expr->value());
   1773     } else {
   1774       EmitBinaryOp(expr->binary_operation(), op, mode);
   1775     }
   1776 
   1777     // Deoptimization point in case the binary operation may have side effects.
   1778     PrepareForBailout(expr->binary_operation(), TOS_REG);
   1779   } else {
   1780     VisitForAccumulatorValue(expr->value());
   1781   }
   1782 
   1783   // Record source position before possible IC call.
   1784   SetSourcePosition(expr->position());
   1785 
   1786   // Store the value.
   1787   switch (assign_type) {
   1788     case VARIABLE:
   1789       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
   1790                              expr->op());
   1791       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
   1792       context()->Plug(r0);
   1793       break;
   1794     case NAMED_PROPERTY:
   1795       EmitNamedPropertyAssignment(expr);
   1796       break;
   1797     case KEYED_PROPERTY:
   1798       EmitKeyedPropertyAssignment(expr);
   1799       break;
   1800   }
   1801 }
   1802 
   1803 
   1804 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   1805   SetSourcePosition(prop->position());
   1806   Literal* key = prop->key()->AsLiteral();
   1807   __ mov(r2, Operand(key->handle()));
   1808   // Call load IC. It has arguments receiver and property name r0 and r2.
   1809   Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   1810   CallIC(ic, RelocInfo::CODE_TARGET, prop->id());
   1811 }
   1812 
   1813 
   1814 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   1815   SetSourcePosition(prop->position());
   1816   // Call keyed load IC. It has arguments key and receiver in r0 and r1.
   1817   Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   1818   CallIC(ic, RelocInfo::CODE_TARGET, prop->id());
   1819 }
   1820 
   1821 
   1822 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
   1823                                               Token::Value op,
   1824                                               OverwriteMode mode,
   1825                                               Expression* left_expr,
   1826                                               Expression* right_expr) {
   1827   Label done, smi_case, stub_call;
   1828 
   1829   Register scratch1 = r2;
   1830   Register scratch2 = r3;
   1831 
   1832   // Get the arguments.
   1833   Register left = r1;
   1834   Register right = r0;
   1835   __ pop(left);
   1836 
   1837   // Perform combined smi check on both operands.
   1838   __ orr(scratch1, left, Operand(right));
   1839   STATIC_ASSERT(kSmiTag == 0);
   1840   JumpPatchSite patch_site(masm_);
   1841   patch_site.EmitJumpIfSmi(scratch1, &smi_case);
   1842 
   1843   __ bind(&stub_call);
   1844   BinaryOpStub stub(op, mode);
   1845   CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
   1846   patch_site.EmitPatchInfo();
   1847   __ jmp(&done);
   1848 
   1849   __ bind(&smi_case);
   1850   // Smi case. This code works the same way as the smi-smi case in the type
   1851   // recording binary operation stub, see
   1852   // BinaryOpStub::GenerateSmiSmiOperation for comments.
   1853   switch (op) {
   1854     case Token::SAR:
   1855       __ b(&stub_call);
   1856       __ GetLeastBitsFromSmi(scratch1, right, 5);
   1857       __ mov(right, Operand(left, ASR, scratch1));
   1858       __ bic(right, right, Operand(kSmiTagMask));
   1859       break;
   1860     case Token::SHL: {
   1861       __ b(&stub_call);
   1862       __ SmiUntag(scratch1, left);
   1863       __ GetLeastBitsFromSmi(scratch2, right, 5);
   1864       __ mov(scratch1, Operand(scratch1, LSL, scratch2));
   1865       __ add(scratch2, scratch1, Operand(0x40000000), SetCC);
   1866       __ b(mi, &stub_call);
   1867       __ SmiTag(right, scratch1);
   1868       break;
   1869     }
   1870     case Token::SHR: {
   1871       __ b(&stub_call);
   1872       __ SmiUntag(scratch1, left);
   1873       __ GetLeastBitsFromSmi(scratch2, right, 5);
   1874       __ mov(scratch1, Operand(scratch1, LSR, scratch2));
   1875       __ tst(scratch1, Operand(0xc0000000));
   1876       __ b(ne, &stub_call);
   1877       __ SmiTag(right, scratch1);
   1878       break;
   1879     }
   1880     case Token::ADD:
   1881       __ add(scratch1, left, Operand(right), SetCC);
   1882       __ b(vs, &stub_call);
   1883       __ mov(right, scratch1);
   1884       break;
   1885     case Token::SUB:
   1886       __ sub(scratch1, left, Operand(right), SetCC);
   1887       __ b(vs, &stub_call);
   1888       __ mov(right, scratch1);
   1889       break;
   1890     case Token::MUL: {
   1891       __ SmiUntag(ip, right);
   1892       __ smull(scratch1, scratch2, left, ip);
   1893       __ mov(ip, Operand(scratch1, ASR, 31));
   1894       __ cmp(ip, Operand(scratch2));
   1895       __ b(ne, &stub_call);
   1896       __ cmp(scratch1, Operand(0));
   1897       __ mov(right, Operand(scratch1), LeaveCC, ne);
   1898       __ b(ne, &done);
   1899       __ add(scratch2, right, Operand(left), SetCC);
   1900       __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl);
   1901       __ b(mi, &stub_call);
   1902       break;
   1903     }
   1904     case Token::BIT_OR:
   1905       __ orr(right, left, Operand(right));
   1906       break;
   1907     case Token::BIT_AND:
   1908       __ and_(right, left, Operand(right));
   1909       break;
   1910     case Token::BIT_XOR:
   1911       __ eor(right, left, Operand(right));
   1912       break;
   1913     default:
   1914       UNREACHABLE();
   1915   }
   1916 
   1917   __ bind(&done);
   1918   context()->Plug(r0);
   1919 }
   1920 
   1921 
   1922 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
   1923                                      Token::Value op,
   1924                                      OverwriteMode mode) {
   1925   __ pop(r1);
   1926   BinaryOpStub stub(op, mode);
   1927   JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
   1928   CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
   1929   patch_site.EmitPatchInfo();
   1930   context()->Plug(r0);
   1931 }
   1932 
   1933 
   1934 void FullCodeGenerator::EmitAssignment(Expression* expr) {
   1935   // Invalid left-hand sides are rewritten to have a 'throw
   1936   // ReferenceError' on the left-hand side.
   1937   if (!expr->IsValidLeftHandSide()) {
   1938     VisitForEffect(expr);
   1939     return;
   1940   }
   1941 
   1942   // Left-hand side can only be a property, a global or a (parameter or local)
   1943   // slot.
   1944   enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
   1945   LhsKind assign_type = VARIABLE;
   1946   Property* prop = expr->AsProperty();
   1947   if (prop != NULL) {
   1948     assign_type = (prop->key()->IsPropertyName())
   1949         ? NAMED_PROPERTY
   1950         : KEYED_PROPERTY;
   1951   }
   1952 
   1953   switch (assign_type) {
   1954     case VARIABLE: {
   1955       Variable* var = expr->AsVariableProxy()->var();
   1956       EffectContext context(this);
   1957       EmitVariableAssignment(var, Token::ASSIGN);
   1958       break;
   1959     }
   1960     case NAMED_PROPERTY: {
   1961       __ push(r0);  // Preserve value.
   1962       VisitForAccumulatorValue(prop->obj());
   1963       __ mov(r1, r0);
   1964       __ pop(r0);  // Restore value.
   1965       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
   1966       Handle<Code> ic = is_classic_mode()
   1967           ? isolate()->builtins()->StoreIC_Initialize()
   1968           : isolate()->builtins()->StoreIC_Initialize_Strict();
   1969       CallIC(ic);
   1970       break;
   1971     }
   1972     case KEYED_PROPERTY: {
   1973       __ push(r0);  // Preserve value.
   1974       VisitForStackValue(prop->obj());
   1975       VisitForAccumulatorValue(prop->key());
   1976       __ mov(r1, r0);
   1977       __ pop(r2);
   1978       __ pop(r0);  // Restore value.
   1979       Handle<Code> ic = is_classic_mode()
   1980           ? isolate()->builtins()->KeyedStoreIC_Initialize()
   1981           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
   1982       CallIC(ic);
   1983       break;
   1984     }
   1985   }
   1986   context()->Plug(r0);
   1987 }
   1988 
   1989 
   1990 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
   1991                                                Token::Value op) {
   1992   if (var->IsUnallocated()) {
   1993     // Global var, const, or let.
   1994     __ mov(r2, Operand(var->name()));
   1995     __ ldr(r1, GlobalObjectOperand());
   1996     Handle<Code> ic = is_classic_mode()
   1997         ? isolate()->builtins()->StoreIC_Initialize()
   1998         : isolate()->builtins()->StoreIC_Initialize_Strict();
   1999     CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
   2000 
   2001   } else if (op == Token::INIT_CONST) {
   2002     // Const initializers need a write barrier.
   2003     ASSERT(!var->IsParameter());  // No const parameters.
   2004     if (var->IsStackLocal()) {
   2005       Label skip;
   2006       __ ldr(r1, StackOperand(var));
   2007       __ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
   2008       __ b(ne, &skip);
   2009       __ str(result_register(), StackOperand(var));
   2010       __ bind(&skip);
   2011     } else {
   2012       ASSERT(var->IsContextSlot() || var->IsLookupSlot());
   2013       // Like var declarations, const declarations are hoisted to function
   2014       // scope.  However, unlike var initializers, const initializers are
   2015       // able to drill a hole to that function context, even from inside a
   2016       // 'with' context.  We thus bypass the normal static scope lookup for
   2017       // var->IsContextSlot().
   2018       __ push(r0);
   2019       __ mov(r0, Operand(var->name()));
   2020       __ Push(cp, r0);  // Context and name.
   2021       __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
   2022     }
   2023 
   2024   } else if (var->mode() == LET && op != Token::INIT_LET) {
   2025     // Non-initializing assignment to let variable needs a write barrier.
   2026     if (var->IsLookupSlot()) {
   2027       __ push(r0);  // Value.
   2028       __ mov(r1, Operand(var->name()));
   2029       __ mov(r0, Operand(Smi::FromInt(language_mode())));
   2030       __ Push(cp, r1, r0);  // Context, name, strict mode.
   2031       __ CallRuntime(Runtime::kStoreContextSlot, 4);
   2032     } else {
   2033       ASSERT(var->IsStackAllocated() || var->IsContextSlot());
   2034       Label assign;
   2035       MemOperand location = VarOperand(var, r1);
   2036       __ ldr(r3, location);
   2037       __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
   2038       __ b(ne, &assign);
   2039       __ mov(r3, Operand(var->name()));
   2040       __ push(r3);
   2041       __ CallRuntime(Runtime::kThrowReferenceError, 1);
   2042       // Perform the assignment.
   2043       __ bind(&assign);
   2044       __ str(result_register(), location);
   2045       if (var->IsContextSlot()) {
   2046         // RecordWrite may destroy all its register arguments.
   2047         __ mov(r3, result_register());
   2048         int offset = Context::SlotOffset(var->index());
   2049         __ RecordWriteContextSlot(
   2050             r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
   2051       }
   2052     }
   2053 
   2054   } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
   2055     // Assignment to var or initializing assignment to let/const
   2056     // in harmony mode.
   2057     if (var->IsStackAllocated() || var->IsContextSlot()) {
   2058       MemOperand location = VarOperand(var, r1);
   2059       if (FLAG_debug_code && op == Token::INIT_LET) {
   2060         // Check for an uninitialized let binding.
   2061         __ ldr(r2, location);
   2062         __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
   2063         __ Check(eq, "Let binding re-initialization.");
   2064       }
   2065       // Perform the assignment.
   2066       __ str(r0, location);
   2067       if (var->IsContextSlot()) {
   2068         __ mov(r3, r0);
   2069         int offset = Context::SlotOffset(var->index());
   2070         __ RecordWriteContextSlot(
   2071             r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
   2072       }
   2073     } else {
   2074       ASSERT(var->IsLookupSlot());
   2075       __ push(r0);  // Value.
   2076       __ mov(r1, Operand(var->name()));
   2077       __ mov(r0, Operand(Smi::FromInt(language_mode())));
   2078       __ Push(cp, r1, r0);  // Context, name, strict mode.
   2079       __ CallRuntime(Runtime::kStoreContextSlot, 4);
   2080     }
   2081   }
   2082   // Non-initializing assignments to consts are ignored.
   2083 }
   2084 
   2085 
   2086 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
   2087   // Assignment to a property, using a named store IC.
   2088   Property* prop = expr->target()->AsProperty();
   2089   ASSERT(prop != NULL);
   2090   ASSERT(prop->key()->AsLiteral() != NULL);
   2091 
   2092   // If the assignment starts a block of assignments to the same object,
   2093   // change to slow case to avoid the quadratic behavior of repeatedly
   2094   // adding fast properties.
   2095   if (expr->starts_initialization_block()) {
   2096     __ push(result_register());
   2097     __ ldr(ip, MemOperand(sp, kPointerSize));  // Receiver is now under value.
   2098     __ push(ip);
   2099     __ CallRuntime(Runtime::kToSlowProperties, 1);
   2100     __ pop(result_register());
   2101   }
   2102 
   2103   // Record source code position before IC call.
   2104   SetSourcePosition(expr->position());
   2105   __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
   2106   // Load receiver to r1. Leave a copy in the stack if needed for turning the
   2107   // receiver into fast case.
   2108   if (expr->ends_initialization_block()) {
   2109     __ ldr(r1, MemOperand(sp));
   2110   } else {
   2111     __ pop(r1);
   2112   }
   2113 
   2114   Handle<Code> ic = is_classic_mode()
   2115       ? isolate()->builtins()->StoreIC_Initialize()
   2116       : isolate()->builtins()->StoreIC_Initialize_Strict();
   2117   CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
   2118 
   2119   // If the assignment ends an initialization block, revert to fast case.
   2120   if (expr->ends_initialization_block()) {
   2121     __ push(r0);  // Result of assignment, saved even if not needed.
   2122     // Receiver is under the result value.
   2123     __ ldr(ip, MemOperand(sp, kPointerSize));
   2124     __ push(ip);
   2125     __ CallRuntime(Runtime::kToFastProperties, 1);
   2126     __ pop(r0);
   2127     __ Drop(1);
   2128   }
   2129   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
   2130   context()->Plug(r0);
   2131 }
   2132 
   2133 
   2134 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
   2135   // Assignment to a property, using a keyed store IC.
   2136 
   2137   // If the assignment starts a block of assignments to the same object,
   2138   // change to slow case to avoid the quadratic behavior of repeatedly
   2139   // adding fast properties.
   2140   if (expr->starts_initialization_block()) {
   2141     __ push(result_register());
   2142     // Receiver is now under the key and value.
   2143     __ ldr(ip, MemOperand(sp, 2 * kPointerSize));
   2144     __ push(ip);
   2145     __ CallRuntime(Runtime::kToSlowProperties, 1);
   2146     __ pop(result_register());
   2147   }
   2148 
   2149   // Record source code position before IC call.
   2150   SetSourcePosition(expr->position());
   2151   __ pop(r1);  // Key.
   2152   // Load receiver to r2. Leave a copy in the stack if needed for turning the
   2153   // receiver into fast case.
   2154   if (expr->ends_initialization_block()) {
   2155     __ ldr(r2, MemOperand(sp));
   2156   } else {
   2157     __ pop(r2);
   2158   }
   2159 
   2160   Handle<Code> ic = is_classic_mode()
   2161       ? isolate()->builtins()->KeyedStoreIC_Initialize()
   2162       : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
   2163   CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
   2164 
   2165   // If the assignment ends an initialization block, revert to fast case.
   2166   if (expr->ends_initialization_block()) {
   2167     __ push(r0);  // Result of assignment, saved even if not needed.
   2168     // Receiver is under the result value.
   2169     __ ldr(ip, MemOperand(sp, kPointerSize));
   2170     __ push(ip);
   2171     __ CallRuntime(Runtime::kToFastProperties, 1);
   2172     __ pop(r0);
   2173     __ Drop(1);
   2174   }
   2175   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
   2176   context()->Plug(r0);
   2177 }
   2178 
   2179 
   2180 void FullCodeGenerator::VisitProperty(Property* expr) {
   2181   Comment cmnt(masm_, "[ Property");
   2182   Expression* key = expr->key();
   2183 
   2184   if (key->IsPropertyName()) {
   2185     VisitForAccumulatorValue(expr->obj());
   2186     EmitNamedPropertyLoad(expr);
   2187     context()->Plug(r0);
   2188   } else {
   2189     VisitForStackValue(expr->obj());
   2190     VisitForAccumulatorValue(expr->key());
   2191     __ pop(r1);
   2192     EmitKeyedPropertyLoad(expr);
   2193     context()->Plug(r0);
   2194   }
   2195 }
   2196 
   2197 
   2198 void FullCodeGenerator::CallIC(Handle<Code> code,
   2199                                RelocInfo::Mode rmode,
   2200                                unsigned ast_id) {
   2201   ic_total_count_++;
   2202   __ Call(code, rmode, ast_id);
   2203 }
   2204 
   2205 void FullCodeGenerator::EmitCallWithIC(Call* expr,
   2206                                        Handle<Object> name,
   2207                                        RelocInfo::Mode mode) {
   2208   // Code common for calls using the IC.
   2209   ZoneList<Expression*>* args = expr->arguments();
   2210   int arg_count = args->length();
   2211   { PreservePositionScope scope(masm()->positions_recorder());
   2212     for (int i = 0; i < arg_count; i++) {
   2213       VisitForStackValue(args->at(i));
   2214     }
   2215     __ mov(r2, Operand(name));
   2216   }
   2217   // Record source position for debugger.
   2218   SetSourcePosition(expr->position());
   2219   // Call the IC initialization code.
   2220   Handle<Code> ic =
   2221       isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
   2222   CallIC(ic, mode, expr->id());
   2223   RecordJSReturnSite(expr);
   2224   // Restore context register.
   2225   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   2226   context()->Plug(r0);
   2227 }
   2228 
   2229 
   2230 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
   2231                                             Expression* key) {
   2232   // Load the key.
   2233   VisitForAccumulatorValue(key);
   2234 
   2235   // Swap the name of the function and the receiver on the stack to follow
   2236   // the calling convention for call ICs.
   2237   __ pop(r1);
   2238   __ push(r0);
   2239   __ push(r1);
   2240 
   2241   // Code common for calls using the IC.
   2242   ZoneList<Expression*>* args = expr->arguments();
   2243   int arg_count = args->length();
   2244   { PreservePositionScope scope(masm()->positions_recorder());
   2245     for (int i = 0; i < arg_count; i++) {
   2246       VisitForStackValue(args->at(i));
   2247     }
   2248   }
   2249   // Record source position for debugger.
   2250   SetSourcePosition(expr->position());
   2251   // Call the IC initialization code.
   2252   Handle<Code> ic =
   2253       isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
   2254   __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize));  // Key.
   2255   CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
   2256   RecordJSReturnSite(expr);
   2257   // Restore context register.
   2258   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   2259   context()->DropAndPlug(1, r0);  // Drop the key still on the stack.
   2260 }
   2261 
   2262 
   2263 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
   2264   // Code common for calls using the call stub.
   2265   ZoneList<Expression*>* args = expr->arguments();
   2266   int arg_count = args->length();
   2267   { PreservePositionScope scope(masm()->positions_recorder());
   2268     for (int i = 0; i < arg_count; i++) {
   2269       VisitForStackValue(args->at(i));
   2270     }
   2271   }
   2272   // Record source position for debugger.
   2273   SetSourcePosition(expr->position());
   2274   CallFunctionStub stub(arg_count, flags);
   2275   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2276   __ CallStub(&stub);
   2277   RecordJSReturnSite(expr);
   2278   // Restore context register.
   2279   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   2280   context()->DropAndPlug(1, r0);
   2281 }
   2282 
   2283 
   2284 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   2285   // Push copy of the first argument or undefined if it doesn't exist.
   2286   if (arg_count > 0) {
   2287     __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
   2288   } else {
   2289     __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
   2290   }
   2291   __ push(r1);
   2292 
   2293   // Push the receiver of the enclosing function.
   2294   int receiver_offset = 2 + info_->scope()->num_parameters();
   2295   __ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize));
   2296   __ push(r1);
   2297   // Push the language mode.
   2298   __ mov(r1, Operand(Smi::FromInt(language_mode())));
   2299   __ push(r1);
   2300 
   2301   // Push the start position of the scope the calls resides in.
   2302   __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
   2303   __ push(r1);
   2304 
   2305   // Do the runtime call.
   2306   __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
   2307 }
   2308 
   2309 
   2310 void FullCodeGenerator::VisitCall(Call* expr) {
   2311 #ifdef DEBUG
   2312   // We want to verify that RecordJSReturnSite gets called on all paths
   2313   // through this function.  Avoid early returns.
   2314   expr->return_is_recorded_ = false;
   2315 #endif
   2316 
   2317   Comment cmnt(masm_, "[ Call");
   2318   Expression* callee = expr->expression();
   2319   VariableProxy* proxy = callee->AsVariableProxy();
   2320   Property* property = callee->AsProperty();
   2321 
   2322   if (proxy != NULL && proxy->var()->is_possibly_eval()) {
   2323     // In a call to eval, we first call %ResolvePossiblyDirectEval to
   2324     // resolve the function we need to call and the receiver of the
   2325     // call.  Then we call the resolved function using the given
   2326     // arguments.
   2327     ZoneList<Expression*>* args = expr->arguments();
   2328     int arg_count = args->length();
   2329 
   2330     { PreservePositionScope pos_scope(masm()->positions_recorder());
   2331       VisitForStackValue(callee);
   2332       __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
   2333       __ push(r2);  // Reserved receiver slot.
   2334 
   2335       // Push the arguments.
   2336       for (int i = 0; i < arg_count; i++) {
   2337         VisitForStackValue(args->at(i));
   2338       }
   2339 
   2340       // Push a copy of the function (found below the arguments) and
   2341       // resolve eval.
   2342       __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2343       __ push(r1);
   2344       EmitResolvePossiblyDirectEval(arg_count);
   2345 
   2346       // The runtime call returns a pair of values in r0 (function) and
   2347       // r1 (receiver). Touch up the stack with the right values.
   2348       __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2349       __ str(r1, MemOperand(sp, arg_count * kPointerSize));
   2350     }
   2351 
   2352     // Record source position for debugger.
   2353     SetSourcePosition(expr->position());
   2354     CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT);
   2355     __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2356     __ CallStub(&stub);
   2357     RecordJSReturnSite(expr);
   2358     // Restore context register.
   2359     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   2360     context()->DropAndPlug(1, r0);
   2361   } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
   2362     // Push global object as receiver for the call IC.
   2363     __ ldr(r0, GlobalObjectOperand());
   2364     __ push(r0);
   2365     EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
   2366   } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
   2367     // Call to a lookup slot (dynamically introduced variable).
   2368     Label slow, done;
   2369 
   2370     { PreservePositionScope scope(masm()->positions_recorder());
   2371       // Generate code for loading from variables potentially shadowed
   2372       // by eval-introduced variables.
   2373       EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
   2374     }
   2375 
   2376     __ bind(&slow);
   2377     // Call the runtime to find the function to call (returned in r0)
   2378     // and the object holding it (returned in edx).
   2379     __ push(context_register());
   2380     __ mov(r2, Operand(proxy->name()));
   2381     __ push(r2);
   2382     __ CallRuntime(Runtime::kLoadContextSlot, 2);
   2383     __ Push(r0, r1);  // Function, receiver.
   2384 
   2385     // If fast case code has been generated, emit code to push the
   2386     // function and receiver and have the slow path jump around this
   2387     // code.
   2388     if (done.is_linked()) {
   2389       Label call;
   2390       __ b(&call);
   2391       __ bind(&done);
   2392       // Push function.
   2393       __ push(r0);
   2394       // The receiver is implicitly the global receiver. Indicate this
   2395       // by passing the hole to the call function stub.
   2396       __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
   2397       __ push(r1);
   2398       __ bind(&call);
   2399     }
   2400 
   2401     // The receiver is either the global receiver or an object found
   2402     // by LoadContextSlot. That object could be the hole if the
   2403     // receiver is implicitly the global object.
   2404     EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
   2405   } else if (property != NULL) {
   2406     { PreservePositionScope scope(masm()->positions_recorder());
   2407       VisitForStackValue(property->obj());
   2408     }
   2409     if (property->key()->IsPropertyName()) {
   2410       EmitCallWithIC(expr,
   2411                      property->key()->AsLiteral()->handle(),
   2412                      RelocInfo::CODE_TARGET);
   2413     } else {
   2414       EmitKeyedCallWithIC(expr, property->key());
   2415     }
   2416   } else {
   2417     // Call to an arbitrary expression not handled specially above.
   2418     { PreservePositionScope scope(masm()->positions_recorder());
   2419       VisitForStackValue(callee);
   2420     }
   2421     // Load global receiver object.
   2422     __ ldr(r1, GlobalObjectOperand());
   2423     __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
   2424     __ push(r1);
   2425     // Emit function call.
   2426     EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
   2427   }
   2428 
   2429 #ifdef DEBUG
   2430   // RecordJSReturnSite should have been called.
   2431   ASSERT(expr->return_is_recorded_);
   2432 #endif
   2433 }
   2434 
   2435 
   2436 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
   2437   Comment cmnt(masm_, "[ CallNew");
   2438   // According to ECMA-262, section 11.2.2, page 44, the function
   2439   // expression in new calls must be evaluated before the
   2440   // arguments.
   2441 
   2442   // Push constructor on the stack.  If it's not a function it's used as
   2443   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
   2444   // ignored.
   2445   VisitForStackValue(expr->expression());
   2446 
   2447   // Push the arguments ("left-to-right") on the stack.
   2448   ZoneList<Expression*>* args = expr->arguments();
   2449   int arg_count = args->length();
   2450   for (int i = 0; i < arg_count; i++) {
   2451     VisitForStackValue(args->at(i));
   2452   }
   2453 
   2454   // Call the construct call builtin that handles allocation and
   2455   // constructor invocation.
   2456   SetSourcePosition(expr->position());
   2457 
   2458   // Load function and argument count into r1 and r0.
   2459   __ mov(r0, Operand(arg_count));
   2460   __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
   2461 
   2462   // Record call targets in unoptimized code, but not in the snapshot.
   2463   CallFunctionFlags flags;
   2464   if (!Serializer::enabled()) {
   2465     flags = RECORD_CALL_TARGET;
   2466     Handle<Object> uninitialized =
   2467         TypeFeedbackCells::UninitializedSentinel(isolate());
   2468     Handle<JSGlobalPropertyCell> cell =
   2469         isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
   2470     RecordTypeFeedbackCell(expr->id(), cell);
   2471     __ mov(r2, Operand(cell));
   2472   } else {
   2473     flags = NO_CALL_FUNCTION_FLAGS;
   2474   }
   2475 
   2476   CallConstructStub stub(flags);
   2477   __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
   2478   PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
   2479   context()->Plug(r0);
   2480 }
   2481 
   2482 
   2483 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
   2484   ZoneList<Expression*>* args = expr->arguments();
   2485   ASSERT(args->length() == 1);
   2486 
   2487   VisitForAccumulatorValue(args->at(0));
   2488 
   2489   Label materialize_true, materialize_false;
   2490   Label* if_true = NULL;
   2491   Label* if_false = NULL;
   2492   Label* fall_through = NULL;
   2493   context()->PrepareTest(&materialize_true, &materialize_false,
   2494                          &if_true, &if_false, &fall_through);
   2495 
   2496   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2497   __ tst(r0, Operand(kSmiTagMask));
   2498   Split(eq, if_true, if_false, fall_through);
   2499 
   2500   context()->Plug(if_true, if_false);
   2501 }
   2502 
   2503 
   2504 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
   2505   ZoneList<Expression*>* args = expr->arguments();
   2506   ASSERT(args->length() == 1);
   2507 
   2508   VisitForAccumulatorValue(args->at(0));
   2509 
   2510   Label materialize_true, materialize_false;
   2511   Label* if_true = NULL;
   2512   Label* if_false = NULL;
   2513   Label* fall_through = NULL;
   2514   context()->PrepareTest(&materialize_true, &materialize_false,
   2515                          &if_true, &if_false, &fall_through);
   2516 
   2517   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2518   __ tst(r0, Operand(kSmiTagMask | 0x80000000));
   2519   Split(eq, if_true, if_false, fall_through);
   2520 
   2521   context()->Plug(if_true, if_false);
   2522 }
   2523 
   2524 
   2525 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
   2526   ZoneList<Expression*>* args = expr->arguments();
   2527   ASSERT(args->length() == 1);
   2528 
   2529   VisitForAccumulatorValue(args->at(0));
   2530 
   2531   Label materialize_true, materialize_false;
   2532   Label* if_true = NULL;
   2533   Label* if_false = NULL;
   2534   Label* fall_through = NULL;
   2535   context()->PrepareTest(&materialize_true, &materialize_false,
   2536                          &if_true, &if_false, &fall_through);
   2537 
   2538   __ JumpIfSmi(r0, if_false);
   2539   __ LoadRoot(ip, Heap::kNullValueRootIndex);
   2540   __ cmp(r0, ip);
   2541   __ b(eq, if_true);
   2542   __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
   2543   // Undetectable objects behave like undefined when tested with typeof.
   2544   __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
   2545   __ tst(r1, Operand(1 << Map::kIsUndetectable));
   2546   __ b(ne, if_false);
   2547   __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
   2548   __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
   2549   __ b(lt, if_false);
   2550   __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
   2551   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2552   Split(le, if_true, if_false, fall_through);
   2553 
   2554   context()->Plug(if_true, if_false);
   2555 }
   2556 
   2557 
   2558 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
   2559   ZoneList<Expression*>* args = expr->arguments();
   2560   ASSERT(args->length() == 1);
   2561 
   2562   VisitForAccumulatorValue(args->at(0));
   2563 
   2564   Label materialize_true, materialize_false;
   2565   Label* if_true = NULL;
   2566   Label* if_false = NULL;
   2567   Label* fall_through = NULL;
   2568   context()->PrepareTest(&materialize_true, &materialize_false,
   2569                          &if_true, &if_false, &fall_through);
   2570 
   2571   __ JumpIfSmi(r0, if_false);
   2572   __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
   2573   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2574   Split(ge, if_true, if_false, fall_through);
   2575 
   2576   context()->Plug(if_true, if_false);
   2577 }
   2578 
   2579 
   2580 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   2581   ZoneList<Expression*>* args = expr->arguments();
   2582   ASSERT(args->length() == 1);
   2583 
   2584   VisitForAccumulatorValue(args->at(0));
   2585 
   2586   Label materialize_true, materialize_false;
   2587   Label* if_true = NULL;
   2588   Label* if_false = NULL;
   2589   Label* fall_through = NULL;
   2590   context()->PrepareTest(&materialize_true, &materialize_false,
   2591                          &if_true, &if_false, &fall_through);
   2592 
   2593   __ JumpIfSmi(r0, if_false);
   2594   __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
   2595   __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
   2596   __ tst(r1, Operand(1 << Map::kIsUndetectable));
   2597   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2598   Split(ne, if_true, if_false, fall_through);
   2599 
   2600   context()->Plug(if_true, if_false);
   2601 }
   2602 
   2603 
   2604 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
   2605     CallRuntime* expr) {
   2606   ZoneList<Expression*>* args = expr->arguments();
   2607   ASSERT(args->length() == 1);
   2608 
   2609   VisitForAccumulatorValue(args->at(0));
   2610 
   2611   Label materialize_true, materialize_false;
   2612   Label* if_true = NULL;
   2613   Label* if_false = NULL;
   2614   Label* fall_through = NULL;
   2615   context()->PrepareTest(&materialize_true, &materialize_false,
   2616                          &if_true, &if_false, &fall_through);
   2617 
   2618   if (FLAG_debug_code) __ AbortIfSmi(r0);
   2619 
   2620   __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
   2621   __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset));
   2622   __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
   2623   __ b(ne, if_true);
   2624 
   2625   // Check for fast case object. Generate false result for slow case object.
   2626   __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset));
   2627   __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
   2628   __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
   2629   __ cmp(r2, ip);
   2630   __ b(eq, if_false);
   2631 
   2632   // Look for valueOf symbol in the descriptor array, and indicate false if
   2633   // found. The type is not checked, so if it is a transition it is a false
   2634   // negative.
   2635   __ LoadInstanceDescriptors(r1, r4);
   2636   __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset));
   2637   // r4: descriptor array
   2638   // r3: length of descriptor array
   2639   // Calculate the end of the descriptor array.
   2640   STATIC_ASSERT(kSmiTag == 0);
   2641   STATIC_ASSERT(kSmiTagSize == 1);
   2642   STATIC_ASSERT(kPointerSize == 4);
   2643   __ add(r2, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   2644   __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
   2645 
   2646   // Calculate location of the first key name.
   2647   __ add(r4,
   2648          r4,
   2649          Operand(FixedArray::kHeaderSize - kHeapObjectTag +
   2650                  DescriptorArray::kFirstIndex * kPointerSize));
   2651   // Loop through all the keys in the descriptor array. If one of these is the
   2652   // symbol valueOf the result is false.
   2653   Label entry, loop;
   2654   // The use of ip to store the valueOf symbol asumes that it is not otherwise
   2655   // used in the loop below.
   2656   __ mov(ip, Operand(FACTORY->value_of_symbol()));
   2657   __ jmp(&entry);
   2658   __ bind(&loop);
   2659   __ ldr(r3, MemOperand(r4, 0));
   2660   __ cmp(r3, ip);
   2661   __ b(eq, if_false);
   2662   __ add(r4, r4, Operand(kPointerSize));
   2663   __ bind(&entry);
   2664   __ cmp(r4, Operand(r2));
   2665   __ b(ne, &loop);
   2666 
   2667   // If a valueOf property is not found on the object check that it's
   2668   // prototype is the un-modified String prototype. If not result is false.
   2669   __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset));
   2670   __ JumpIfSmi(r2, if_false);
   2671   __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
   2672   __ ldr(r3, ContextOperand(cp, Context::GLOBAL_INDEX));
   2673   __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset));
   2674   __ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
   2675   __ cmp(r2, r3);
   2676   __ b(ne, if_false);
   2677 
   2678   // Set the bit in the map to indicate that it has been checked safe for
   2679   // default valueOf and set true result.
   2680   __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
   2681   __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
   2682   __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
   2683   __ jmp(if_true);
   2684 
   2685   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2686   context()->Plug(if_true, if_false);
   2687 }
   2688 
   2689 
   2690 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
   2691   ZoneList<Expression*>* args = expr->arguments();
   2692   ASSERT(args->length() == 1);
   2693 
   2694   VisitForAccumulatorValue(args->at(0));
   2695 
   2696   Label materialize_true, materialize_false;
   2697   Label* if_true = NULL;
   2698   Label* if_false = NULL;
   2699   Label* fall_through = NULL;
   2700   context()->PrepareTest(&materialize_true, &materialize_false,
   2701                          &if_true, &if_false, &fall_through);
   2702 
   2703   __ JumpIfSmi(r0, if_false);
   2704   __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
   2705   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2706   Split(eq, if_true, if_false, fall_through);
   2707 
   2708   context()->Plug(if_true, if_false);
   2709 }
   2710 
   2711 
   2712 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
   2713   ZoneList<Expression*>* args = expr->arguments();
   2714   ASSERT(args->length() == 1);
   2715 
   2716   VisitForAccumulatorValue(args->at(0));
   2717 
   2718   Label materialize_true, materialize_false;
   2719   Label* if_true = NULL;
   2720   Label* if_false = NULL;
   2721   Label* fall_through = NULL;
   2722   context()->PrepareTest(&materialize_true, &materialize_false,
   2723                          &if_true, &if_false, &fall_through);
   2724 
   2725   __ JumpIfSmi(r0, if_false);
   2726   __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
   2727   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2728   Split(eq, if_true, if_false, fall_through);
   2729 
   2730   context()->Plug(if_true, if_false);
   2731 }
   2732 
   2733 
   2734 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
   2735   ZoneList<Expression*>* args = expr->arguments();
   2736   ASSERT(args->length() == 1);
   2737 
   2738   VisitForAccumulatorValue(args->at(0));
   2739 
   2740   Label materialize_true, materialize_false;
   2741   Label* if_true = NULL;
   2742   Label* if_false = NULL;
   2743   Label* fall_through = NULL;
   2744   context()->PrepareTest(&materialize_true, &materialize_false,
   2745                          &if_true, &if_false, &fall_through);
   2746 
   2747   __ JumpIfSmi(r0, if_false);
   2748   __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
   2749   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2750   Split(eq, if_true, if_false, fall_through);
   2751 
   2752   context()->Plug(if_true, if_false);
   2753 }
   2754 
   2755 
   2756 
   2757 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
   2758   ASSERT(expr->arguments()->length() == 0);
   2759 
   2760   Label materialize_true, materialize_false;
   2761   Label* if_true = NULL;
   2762   Label* if_false = NULL;
   2763   Label* fall_through = NULL;
   2764   context()->PrepareTest(&materialize_true, &materialize_false,
   2765                          &if_true, &if_false, &fall_through);
   2766 
   2767   // Get the frame pointer for the calling frame.
   2768   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   2769 
   2770   // Skip the arguments adaptor frame if it exists.
   2771   Label check_frame_marker;
   2772   __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
   2773   __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   2774   __ b(ne, &check_frame_marker);
   2775   __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
   2776 
   2777   // Check the marker in the calling frame.
   2778   __ bind(&check_frame_marker);
   2779   __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
   2780   __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
   2781   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2782   Split(eq, if_true, if_false, fall_through);
   2783 
   2784   context()->Plug(if_true, if_false);
   2785 }
   2786 
   2787 
   2788 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
   2789   ZoneList<Expression*>* args = expr->arguments();
   2790   ASSERT(args->length() == 2);
   2791 
   2792   // Load the two objects into registers and perform the comparison.
   2793   VisitForStackValue(args->at(0));
   2794   VisitForAccumulatorValue(args->at(1));
   2795 
   2796   Label materialize_true, materialize_false;
   2797   Label* if_true = NULL;
   2798   Label* if_false = NULL;
   2799   Label* fall_through = NULL;
   2800   context()->PrepareTest(&materialize_true, &materialize_false,
   2801                          &if_true, &if_false, &fall_through);
   2802 
   2803   __ pop(r1);
   2804   __ cmp(r0, r1);
   2805   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2806   Split(eq, if_true, if_false, fall_through);
   2807 
   2808   context()->Plug(if_true, if_false);
   2809 }
   2810 
   2811 
   2812 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
   2813   ZoneList<Expression*>* args = expr->arguments();
   2814   ASSERT(args->length() == 1);
   2815 
   2816   // ArgumentsAccessStub expects the key in edx and the formal
   2817   // parameter count in r0.
   2818   VisitForAccumulatorValue(args->at(0));
   2819   __ mov(r1, r0);
   2820   __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
   2821   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
   2822   __ CallStub(&stub);
   2823   context()->Plug(r0);
   2824 }
   2825 
   2826 
   2827 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
   2828   ASSERT(expr->arguments()->length() == 0);
   2829   Label exit;
   2830   // Get the number of formal parameters.
   2831   __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
   2832 
   2833   // Check if the calling frame is an arguments adaptor frame.
   2834   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   2835   __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
   2836   __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   2837   __ b(ne, &exit);
   2838 
   2839   // Arguments adaptor case: Read the arguments length from the
   2840   // adaptor frame.
   2841   __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
   2842 
   2843   __ bind(&exit);
   2844   context()->Plug(r0);
   2845 }
   2846 
   2847 
   2848 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
   2849   ZoneList<Expression*>* args = expr->arguments();
   2850   ASSERT(args->length() == 1);
   2851   Label done, null, function, non_function_constructor;
   2852 
   2853   VisitForAccumulatorValue(args->at(0));
   2854 
   2855   // If the object is a smi, we return null.
   2856   __ JumpIfSmi(r0, &null);
   2857 
   2858   // Check that the object is a JS object but take special care of JS
   2859   // functions to make sure they have 'Function' as their class.
   2860   // Assume that there are only two callable types, and one of them is at
   2861   // either end of the type range for JS object types. Saves extra comparisons.
   2862   STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
   2863   __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE);
   2864   // Map is now in r0.
   2865   __ b(lt, &null);
   2866   STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
   2867                 FIRST_SPEC_OBJECT_TYPE + 1);
   2868   __ b(eq, &function);
   2869 
   2870   __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE));
   2871   STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
   2872                 LAST_SPEC_OBJECT_TYPE - 1);
   2873   __ b(eq, &function);
   2874   // Assume that there is no larger type.
   2875   STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
   2876 
   2877   // Check if the constructor in the map is a JS function.
   2878   __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
   2879   __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
   2880   __ b(ne, &non_function_constructor);
   2881 
   2882   // r0 now contains the constructor function. Grab the
   2883   // instance class name from there.
   2884   __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
   2885   __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
   2886   __ b(&done);
   2887 
   2888   // Functions have class 'Function'.
   2889   __ bind(&function);
   2890   __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
   2891   __ jmp(&done);
   2892 
   2893   // Objects with a non-function constructor have class 'Object'.
   2894   __ bind(&non_function_constructor);
   2895   __ LoadRoot(r0, Heap::kObject_symbolRootIndex);
   2896   __ jmp(&done);
   2897 
   2898   // Non-JS objects have class null.
   2899   __ bind(&null);
   2900   __ LoadRoot(r0, Heap::kNullValueRootIndex);
   2901 
   2902   // All done.
   2903   __ bind(&done);
   2904 
   2905   context()->Plug(r0);
   2906 }
   2907 
   2908 
   2909 void FullCodeGenerator::EmitLog(CallRuntime* expr) {
   2910   // Conditionally generate a log call.
   2911   // Args:
   2912   //   0 (literal string): The type of logging (corresponds to the flags).
   2913   //     This is used to determine whether or not to generate the log call.
   2914   //   1 (string): Format string.  Access the string at argument index 2
   2915   //     with '%2s' (see Logger::LogRuntime for all the formats).
   2916   //   2 (array): Arguments to the format string.
   2917   ZoneList<Expression*>* args = expr->arguments();
   2918   ASSERT_EQ(args->length(), 3);
   2919   if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
   2920     VisitForStackValue(args->at(1));
   2921     VisitForStackValue(args->at(2));
   2922     __ CallRuntime(Runtime::kLog, 2);
   2923   }
   2924 
   2925   // Finally, we're expected to leave a value on the top of the stack.
   2926   __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
   2927   context()->Plug(r0);
   2928 }
   2929 
   2930 
   2931 void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
   2932   ASSERT(expr->arguments()->length() == 0);
   2933   Label slow_allocate_heapnumber;
   2934   Label heapnumber_allocated;
   2935 
   2936   __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
   2937   __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
   2938   __ jmp(&heapnumber_allocated);
   2939 
   2940   __ bind(&slow_allocate_heapnumber);
   2941   // Allocate a heap number.
   2942   __ CallRuntime(Runtime::kNumberAlloc, 0);
   2943   __ mov(r4, Operand(r0));
   2944 
   2945   __ bind(&heapnumber_allocated);
   2946 
   2947   // Convert 32 random bits in r0 to 0.(32 random bits) in a double
   2948   // by computing:
   2949   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
   2950   if (CpuFeatures::IsSupported(VFP3)) {
   2951     __ PrepareCallCFunction(1, r0);
   2952     __ ldr(r0, ContextOperand(context_register(), Context::GLOBAL_INDEX));
   2953     __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
   2954     __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
   2955 
   2956     CpuFeatures::Scope scope(VFP3);
   2957     // 0x41300000 is the top half of 1.0 x 2^20 as a double.
   2958     // Create this constant using mov/orr to avoid PC relative load.
   2959     __ mov(r1, Operand(0x41000000));
   2960     __ orr(r1, r1, Operand(0x300000));
   2961     // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
   2962     __ vmov(d7, r0, r1);
   2963     // Move 0x4130000000000000 to VFP.
   2964     __ mov(r0, Operand(0, RelocInfo::NONE));
   2965     __ vmov(d8, r0, r1);
   2966     // Subtract and store the result in the heap number.
   2967     __ vsub(d7, d7, d8);
   2968     __ sub(r0, r4, Operand(kHeapObjectTag));
   2969     __ vstr(d7, r0, HeapNumber::kValueOffset);
   2970     __ mov(r0, r4);
   2971   } else {
   2972     __ PrepareCallCFunction(2, r0);
   2973     __ ldr(r1, ContextOperand(context_register(), Context::GLOBAL_INDEX));
   2974     __ mov(r0, Operand(r4));
   2975     __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset));
   2976     __ CallCFunction(
   2977         ExternalReference::fill_heap_number_with_random_function(isolate()), 2);
   2978   }
   2979 
   2980   context()->Plug(r0);
   2981 }
   2982 
   2983 
   2984 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
   2985   // Load the arguments on the stack and call the stub.
   2986   SubStringStub stub;
   2987   ZoneList<Expression*>* args = expr->arguments();
   2988   ASSERT(args->length() == 3);
   2989   VisitForStackValue(args->at(0));
   2990   VisitForStackValue(args->at(1));
   2991   VisitForStackValue(args->at(2));
   2992   __ CallStub(&stub);
   2993   context()->Plug(r0);
   2994 }
   2995 
   2996 
   2997 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
   2998   // Load the arguments on the stack and call the stub.
   2999   RegExpExecStub stub;
   3000   ZoneList<Expression*>* args = expr->arguments();
   3001   ASSERT(args->length() == 4);
   3002   VisitForStackValue(args->at(0));
   3003   VisitForStackValue(args->at(1));
   3004   VisitForStackValue(args->at(2));
   3005   VisitForStackValue(args->at(3));
   3006   __ CallStub(&stub);
   3007   context()->Plug(r0);
   3008 }
   3009 
   3010 
   3011 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
   3012   ZoneList<Expression*>* args = expr->arguments();
   3013   ASSERT(args->length() == 1);
   3014   VisitForAccumulatorValue(args->at(0));  // Load the object.
   3015 
   3016   Label done;
   3017   // If the object is a smi return the object.
   3018   __ JumpIfSmi(r0, &done);
   3019   // If the object is not a value type, return the object.
   3020   __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
   3021   __ b(ne, &done);
   3022   __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
   3023 
   3024   __ bind(&done);
   3025   context()->Plug(r0);
   3026 }
   3027 
   3028 
   3029 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
   3030   ZoneList<Expression*>* args = expr->arguments();
   3031   ASSERT(args->length() == 2);
   3032   ASSERT_NE(NULL, args->at(1)->AsLiteral());
   3033   Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle()));
   3034 
   3035   VisitForAccumulatorValue(args->at(0));  // Load the object.
   3036 
   3037   Label runtime, done;
   3038   Register object = r0;
   3039   Register result = r0;
   3040   Register scratch0 = r9;
   3041   Register scratch1 = r1;
   3042 
   3043 #ifdef DEBUG
   3044   __ AbortIfSmi(object);
   3045   __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE);
   3046   __ Assert(eq, "Trying to get date field from non-date.");
   3047 #endif
   3048 
   3049   if (index->value() == 0) {
   3050     __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
   3051   } else {
   3052     if (index->value() < JSDate::kFirstUncachedField) {
   3053       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
   3054       __ mov(scratch1, Operand(stamp));
   3055       __ ldr(scratch1, MemOperand(scratch1));
   3056       __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset));
   3057       __ cmp(scratch1, scratch0);
   3058       __ b(ne, &runtime);
   3059       __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset +
   3060                                              kPointerSize * index->value()));
   3061       __ jmp(&done);
   3062     }
   3063     __ bind(&runtime);
   3064     __ PrepareCallCFunction(2, scratch1);
   3065     __ mov(r1, Operand(index));
   3066     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
   3067     __ bind(&done);
   3068   }
   3069   context()->Plug(r0);
   3070 }
   3071 
   3072 
   3073 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
   3074   // Load the arguments on the stack and call the runtime function.
   3075   ZoneList<Expression*>* args = expr->arguments();
   3076   ASSERT(args->length() == 2);
   3077   VisitForStackValue(args->at(0));
   3078   VisitForStackValue(args->at(1));
   3079   if (CpuFeatures::IsSupported(VFP3)) {
   3080     MathPowStub stub(MathPowStub::ON_STACK);
   3081     __ CallStub(&stub);
   3082   } else {
   3083     __ CallRuntime(Runtime::kMath_pow, 2);
   3084   }
   3085   context()->Plug(r0);
   3086 }
   3087 
   3088 
   3089 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
   3090   ZoneList<Expression*>* args = expr->arguments();
   3091   ASSERT(args->length() == 2);
   3092   VisitForStackValue(args->at(0));  // Load the object.
   3093   VisitForAccumulatorValue(args->at(1));  // Load the value.
   3094   __ pop(r1);  // r0 = value. r1 = object.
   3095 
   3096   Label done;
   3097   // If the object is a smi, return the value.
   3098   __ JumpIfSmi(r1, &done);
   3099 
   3100   // If the object is not a value type, return the value.
   3101   __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
   3102   __ b(ne, &done);
   3103 
   3104   // Store the value.
   3105   __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
   3106   // Update the write barrier.  Save the value as it will be
   3107   // overwritten by the write barrier code and is needed afterward.
   3108   __ mov(r2, r0);
   3109   __ RecordWriteField(
   3110       r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
   3111 
   3112   __ bind(&done);
   3113   context()->Plug(r0);
   3114 }
   3115 
   3116 
   3117 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
   3118   ZoneList<Expression*>* args = expr->arguments();
   3119   ASSERT_EQ(args->length(), 1);
   3120   // Load the argument on the stack and call the stub.
   3121   VisitForStackValue(args->at(0));
   3122 
   3123   NumberToStringStub stub;
   3124   __ CallStub(&stub);
   3125   context()->Plug(r0);
   3126 }
   3127 
   3128 
   3129 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   3130   ZoneList<Expression*>* args = expr->arguments();
   3131   ASSERT(args->length() == 1);
   3132   VisitForAccumulatorValue(args->at(0));
   3133 
   3134   Label done;
   3135   StringCharFromCodeGenerator generator(r0, r1);
   3136   generator.GenerateFast(masm_);
   3137   __ jmp(&done);
   3138 
   3139   NopRuntimeCallHelper call_helper;
   3140   generator.GenerateSlow(masm_, call_helper);
   3141 
   3142   __ bind(&done);
   3143   context()->Plug(r1);
   3144 }
   3145 
   3146 
   3147 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
   3148   ZoneList<Expression*>* args = expr->arguments();
   3149   ASSERT(args->length() == 2);
   3150   VisitForStackValue(args->at(0));
   3151   VisitForAccumulatorValue(args->at(1));
   3152 
   3153   Register object = r1;
   3154   Register index = r0;
   3155   Register result = r3;
   3156 
   3157   __ pop(object);
   3158 
   3159   Label need_conversion;
   3160   Label index_out_of_range;
   3161   Label done;
   3162   StringCharCodeAtGenerator generator(object,
   3163                                       index,
   3164                                       result,
   3165                                       &need_conversion,
   3166                                       &need_conversion,
   3167                                       &index_out_of_range,
   3168                                       STRING_INDEX_IS_NUMBER);
   3169   generator.GenerateFast(masm_);
   3170   __ jmp(&done);
   3171 
   3172   __ bind(&index_out_of_range);
   3173   // When the index is out of range, the spec requires us to return
   3174   // NaN.
   3175   __ LoadRoot(result, Heap::kNanValueRootIndex);
   3176   __ jmp(&done);
   3177 
   3178   __ bind(&need_conversion);
   3179   // Load the undefined value into the result register, which will
   3180   // trigger conversion.
   3181   __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
   3182   __ jmp(&done);
   3183 
   3184   NopRuntimeCallHelper call_helper;
   3185   generator.GenerateSlow(masm_, call_helper);
   3186 
   3187   __ bind(&done);
   3188   context()->Plug(result);
   3189 }
   3190 
   3191 
   3192 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
   3193   ZoneList<Expression*>* args = expr->arguments();
   3194   ASSERT(args->length() == 2);
   3195   VisitForStackValue(args->at(0));
   3196   VisitForAccumulatorValue(args->at(1));
   3197 
   3198   Register object = r1;
   3199   Register index = r0;
   3200   Register scratch = r3;
   3201   Register result = r0;
   3202 
   3203   __ pop(object);
   3204 
   3205   Label need_conversion;
   3206   Label index_out_of_range;
   3207   Label done;
   3208   StringCharAtGenerator generator(object,
   3209                                   index,
   3210                                   scratch,
   3211                                   result,
   3212                                   &need_conversion,
   3213                                   &need_conversion,
   3214                                   &index_out_of_range,
   3215                                   STRING_INDEX_IS_NUMBER);
   3216   generator.GenerateFast(masm_);
   3217   __ jmp(&done);
   3218 
   3219   __ bind(&index_out_of_range);
   3220   // When the index is out of range, the spec requires us to return
   3221   // the empty string.
   3222   __ LoadRoot(result, Heap::kEmptyStringRootIndex);
   3223   __ jmp(&done);
   3224 
   3225   __ bind(&need_conversion);
   3226   // Move smi zero into the result register, which will trigger
   3227   // conversion.
   3228   __ mov(result, Operand(Smi::FromInt(0)));
   3229   __ jmp(&done);
   3230 
   3231   NopRuntimeCallHelper call_helper;
   3232   generator.GenerateSlow(masm_, call_helper);
   3233 
   3234   __ bind(&done);
   3235   context()->Plug(result);
   3236 }
   3237 
   3238 
   3239 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
   3240   ZoneList<Expression*>* args = expr->arguments();
   3241   ASSERT_EQ(2, args->length());
   3242   VisitForStackValue(args->at(0));
   3243   VisitForStackValue(args->at(1));
   3244 
   3245   StringAddStub stub(NO_STRING_ADD_FLAGS);
   3246   __ CallStub(&stub);
   3247   context()->Plug(r0);
   3248 }
   3249 
   3250 
   3251 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
   3252   ZoneList<Expression*>* args = expr->arguments();
   3253   ASSERT_EQ(2, args->length());
   3254   VisitForStackValue(args->at(0));
   3255   VisitForStackValue(args->at(1));
   3256 
   3257   StringCompareStub stub;
   3258   __ CallStub(&stub);
   3259   context()->Plug(r0);
   3260 }
   3261 
   3262 
   3263 void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
   3264   // Load the argument on the stack and call the stub.
   3265   TranscendentalCacheStub stub(TranscendentalCache::SIN,
   3266                                TranscendentalCacheStub::TAGGED);
   3267   ZoneList<Expression*>* args = expr->arguments();
   3268   ASSERT(args->length() == 1);
   3269   VisitForStackValue(args->at(0));
   3270   __ CallStub(&stub);
   3271   context()->Plug(r0);
   3272 }
   3273 
   3274 
   3275 void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
   3276   // Load the argument on the stack and call the stub.
   3277   TranscendentalCacheStub stub(TranscendentalCache::COS,
   3278                                TranscendentalCacheStub::TAGGED);
   3279   ZoneList<Expression*>* args = expr->arguments();
   3280   ASSERT(args->length() == 1);
   3281   VisitForStackValue(args->at(0));
   3282   __ CallStub(&stub);
   3283   context()->Plug(r0);
   3284 }
   3285 
   3286 
   3287 void FullCodeGenerator::EmitMathTan(CallRuntime* expr) {
   3288   // Load the argument on the stack and call the stub.
   3289   TranscendentalCacheStub stub(TranscendentalCache::TAN,
   3290                                TranscendentalCacheStub::TAGGED);
   3291   ZoneList<Expression*>* args = expr->arguments();
   3292   ASSERT(args->length() == 1);
   3293   VisitForStackValue(args->at(0));
   3294   __ CallStub(&stub);
   3295   context()->Plug(r0);
   3296 }
   3297 
   3298 
   3299 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
   3300   // Load the argument on the stack and call the stub.
   3301   TranscendentalCacheStub stub(TranscendentalCache::LOG,
   3302                                TranscendentalCacheStub::TAGGED);
   3303   ZoneList<Expression*>* args = expr->arguments();
   3304   ASSERT(args->length() == 1);
   3305   VisitForStackValue(args->at(0));
   3306   __ CallStub(&stub);
   3307   context()->Plug(r0);
   3308 }
   3309 
   3310 
   3311 void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
   3312   // Load the argument on the stack and call the runtime function.
   3313   ZoneList<Expression*>* args = expr->arguments();
   3314   ASSERT(args->length() == 1);
   3315   VisitForStackValue(args->at(0));
   3316   __ CallRuntime(Runtime::kMath_sqrt, 1);
   3317   context()->Plug(r0);
   3318 }
   3319 
   3320 
   3321 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
   3322   ZoneList<Expression*>* args = expr->arguments();
   3323   ASSERT(args->length() >= 2);
   3324 
   3325   int arg_count = args->length() - 2;  // 2 ~ receiver and function.
   3326   for (int i = 0; i < arg_count + 1; i++) {
   3327     VisitForStackValue(args->at(i));
   3328   }
   3329   VisitForAccumulatorValue(args->last());  // Function.
   3330 
   3331   // Check for proxy.
   3332   Label proxy, done;
   3333   __ CompareObjectType(r0, r1, r1, JS_FUNCTION_PROXY_TYPE);
   3334   __ b(eq, &proxy);
   3335 
   3336   // InvokeFunction requires the function in r1. Move it in there.
   3337   __ mov(r1, result_register());
   3338   ParameterCount count(arg_count);
   3339   __ InvokeFunction(r1, count, CALL_FUNCTION,
   3340                     NullCallWrapper(), CALL_AS_METHOD);
   3341   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   3342   __ jmp(&done);
   3343 
   3344   __ bind(&proxy);
   3345   __ push(r0);
   3346   __ CallRuntime(Runtime::kCall, args->length());
   3347   __ bind(&done);
   3348 
   3349   context()->Plug(r0);
   3350 }
   3351 
   3352 
   3353 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
   3354   RegExpConstructResultStub stub;
   3355   ZoneList<Expression*>* args = expr->arguments();
   3356   ASSERT(args->length() == 3);
   3357   VisitForStackValue(args->at(0));
   3358   VisitForStackValue(args->at(1));
   3359   VisitForStackValue(args->at(2));
   3360   __ CallStub(&stub);
   3361   context()->Plug(r0);
   3362 }
   3363 
   3364 
   3365 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
   3366   ZoneList<Expression*>* args = expr->arguments();
   3367   ASSERT_EQ(2, args->length());
   3368   ASSERT_NE(NULL, args->at(0)->AsLiteral());
   3369   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
   3370 
   3371   Handle<FixedArray> jsfunction_result_caches(
   3372       isolate()->global_context()->jsfunction_result_caches());
   3373   if (jsfunction_result_caches->length() <= cache_id) {
   3374     __ Abort("Attempt to use undefined cache.");
   3375     __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
   3376     context()->Plug(r0);
   3377     return;
   3378   }
   3379 
   3380   VisitForAccumulatorValue(args->at(1));
   3381 
   3382   Register key = r0;
   3383   Register cache = r1;
   3384   __ ldr(cache, ContextOperand(cp, Context::GLOBAL_INDEX));
   3385   __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset));
   3386   __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
   3387   __ ldr(cache,
   3388          FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
   3389 
   3390 
   3391   Label done, not_found;
   3392   // tmp now holds finger offset as a smi.
   3393   STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
   3394   __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
   3395   // r2 now holds finger offset as a smi.
   3396   __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   3397   // r3 now points to the start of fixed array elements.
   3398   __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex));
   3399   // Note side effect of PreIndex: r3 now points to the key of the pair.
   3400   __ cmp(key, r2);
   3401   __ b(ne, &not_found);
   3402 
   3403   __ ldr(r0, MemOperand(r3, kPointerSize));
   3404   __ b(&done);
   3405 
   3406   __ bind(&not_found);
   3407   // Call runtime to perform the lookup.
   3408   __ Push(cache, key);
   3409   __ CallRuntime(Runtime::kGetFromCache, 2);
   3410 
   3411   __ bind(&done);
   3412   context()->Plug(r0);
   3413 }
   3414 
   3415 
   3416 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
   3417   ZoneList<Expression*>* args = expr->arguments();
   3418   ASSERT_EQ(2, args->length());
   3419 
   3420   Register right = r0;
   3421   Register left = r1;
   3422   Register tmp = r2;
   3423   Register tmp2 = r3;
   3424 
   3425   VisitForStackValue(args->at(0));
   3426   VisitForAccumulatorValue(args->at(1));
   3427   __ pop(left);
   3428 
   3429   Label done, fail, ok;
   3430   __ cmp(left, Operand(right));
   3431   __ b(eq, &ok);
   3432   // Fail if either is a non-HeapObject.
   3433   __ and_(tmp, left, Operand(right));
   3434   __ JumpIfSmi(tmp, &fail);
   3435   __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
   3436   __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
   3437   __ cmp(tmp2, Operand(JS_REGEXP_TYPE));
   3438   __ b(ne, &fail);
   3439   __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
   3440   __ cmp(tmp, Operand(tmp2));
   3441   __ b(ne, &fail);
   3442   __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
   3443   __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
   3444   __ cmp(tmp, tmp2);
   3445   __ b(eq, &ok);
   3446   __ bind(&fail);
   3447   __ LoadRoot(r0, Heap::kFalseValueRootIndex);
   3448   __ jmp(&done);
   3449   __ bind(&ok);
   3450   __ LoadRoot(r0, Heap::kTrueValueRootIndex);
   3451   __ bind(&done);
   3452 
   3453   context()->Plug(r0);
   3454 }
   3455 
   3456 
   3457 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
   3458   ZoneList<Expression*>* args = expr->arguments();
   3459   VisitForAccumulatorValue(args->at(0));
   3460 
   3461   Label materialize_true, materialize_false;
   3462   Label* if_true = NULL;
   3463   Label* if_false = NULL;
   3464   Label* fall_through = NULL;
   3465   context()->PrepareTest(&materialize_true, &materialize_false,
   3466                          &if_true, &if_false, &fall_through);
   3467 
   3468   __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
   3469   __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
   3470   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   3471   Split(eq, if_true, if_false, fall_through);
   3472 
   3473   context()->Plug(if_true, if_false);
   3474 }
   3475 
   3476 
   3477 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
   3478   ZoneList<Expression*>* args = expr->arguments();
   3479   ASSERT(args->length() == 1);
   3480   VisitForAccumulatorValue(args->at(0));
   3481 
   3482   if (FLAG_debug_code) {
   3483     __ AbortIfNotString(r0);
   3484   }
   3485 
   3486   __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
   3487   __ IndexFromHash(r0, r0);
   3488 
   3489   context()->Plug(r0);
   3490 }
   3491 
   3492 
   3493 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
   3494   Label bailout, done, one_char_separator, long_separator,
   3495       non_trivial_array, not_size_one_array, loop,
   3496       empty_separator_loop, one_char_separator_loop,
   3497       one_char_separator_loop_entry, long_separator_loop;
   3498   ZoneList<Expression*>* args = expr->arguments();
   3499   ASSERT(args->length() == 2);
   3500   VisitForStackValue(args->at(1));
   3501   VisitForAccumulatorValue(args->at(0));
   3502 
   3503   // All aliases of the same register have disjoint lifetimes.
   3504   Register array = r0;
   3505   Register elements = no_reg;  // Will be r0.
   3506   Register result = no_reg;  // Will be r0.
   3507   Register separator = r1;
   3508   Register array_length = r2;
   3509   Register result_pos = no_reg;  // Will be r2
   3510   Register string_length = r3;
   3511   Register string = r4;
   3512   Register element = r5;
   3513   Register elements_end = r6;
   3514   Register scratch1 = r7;
   3515   Register scratch2 = r9;
   3516 
   3517   // Separator operand is on the stack.
   3518   __ pop(separator);
   3519 
   3520   // Check that the array is a JSArray.
   3521   __ JumpIfSmi(array, &bailout);
   3522   __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE);
   3523   __ b(ne, &bailout);
   3524 
   3525   // Check that the array has fast elements.
   3526   __ CheckFastElements(scratch1, scratch2, &bailout);
   3527 
   3528   // If the array has length zero, return the empty string.
   3529   __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
   3530   __ SmiUntag(array_length, SetCC);
   3531   __ b(ne, &non_trivial_array);
   3532   __ LoadRoot(r0, Heap::kEmptyStringRootIndex);
   3533   __ b(&done);
   3534 
   3535   __ bind(&non_trivial_array);
   3536 
   3537   // Get the FixedArray containing array's elements.
   3538   elements = array;
   3539   __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset));
   3540   array = no_reg;  // End of array's live range.
   3541 
   3542   // Check that all array elements are sequential ASCII strings, and
   3543   // accumulate the sum of their lengths, as a smi-encoded value.
   3544   __ mov(string_length, Operand(0));
   3545   __ add(element,
   3546          elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   3547   __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
   3548   // Loop condition: while (element < elements_end).
   3549   // Live values in registers:
   3550   //   elements: Fixed array of strings.
   3551   //   array_length: Length of the fixed array of strings (not smi)
   3552   //   separator: Separator string
   3553   //   string_length: Accumulated sum of string lengths (smi).
   3554   //   element: Current array element.
   3555   //   elements_end: Array end.
   3556   if (FLAG_debug_code) {
   3557     __ cmp(array_length, Operand(0));
   3558     __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin");
   3559   }
   3560   __ bind(&loop);
   3561   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
   3562   __ JumpIfSmi(string, &bailout);
   3563   __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
   3564   __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
   3565   __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
   3566   __ ldr(scratch1, FieldMemOperand(string, SeqAsciiString::kLengthOffset));
   3567   __ add(string_length, string_length, Operand(scratch1));
   3568   __ b(vs, &bailout);
   3569   __ cmp(element, elements_end);
   3570   __ b(lt, &loop);
   3571 
   3572   // If array_length is 1, return elements[0], a string.
   3573   __ cmp(array_length, Operand(1));
   3574   __ b(ne, &not_size_one_array);
   3575   __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
   3576   __ b(&done);
   3577 
   3578   __ bind(&not_size_one_array);
   3579 
   3580   // Live values in registers:
   3581   //   separator: Separator string
   3582   //   array_length: Length of the array.
   3583   //   string_length: Sum of string lengths (smi).
   3584   //   elements: FixedArray of strings.
   3585 
   3586   // Check that the separator is a flat ASCII string.
   3587   __ JumpIfSmi(separator, &bailout);
   3588   __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
   3589   __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
   3590   __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
   3591 
   3592   // Add (separator length times array_length) - separator length to the
   3593   // string_length to get the length of the result string. array_length is not
   3594   // smi but the other values are, so the result is a smi
   3595   __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
   3596   __ sub(string_length, string_length, Operand(scratch1));
   3597   __ smull(scratch2, ip, array_length, scratch1);
   3598   // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
   3599   // zero.
   3600   __ cmp(ip, Operand(0));
   3601   __ b(ne, &bailout);
   3602   __ tst(scratch2, Operand(0x80000000));
   3603   __ b(ne, &bailout);
   3604   __ add(string_length, string_length, Operand(scratch2));
   3605   __ b(vs, &bailout);
   3606   __ SmiUntag(string_length);
   3607 
   3608   // Get first element in the array to free up the elements register to be used
   3609   // for the result.
   3610   __ add(element,
   3611          elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   3612   result = elements;  // End of live range for elements.
   3613   elements = no_reg;
   3614   // Live values in registers:
   3615   //   element: First array element
   3616   //   separator: Separator string
   3617   //   string_length: Length of result string (not smi)
   3618   //   array_length: Length of the array.
   3619   __ AllocateAsciiString(result,
   3620                          string_length,
   3621                          scratch1,
   3622                          scratch2,
   3623                          elements_end,
   3624                          &bailout);
   3625   // Prepare for looping. Set up elements_end to end of the array. Set
   3626   // result_pos to the position of the result where to write the first
   3627   // character.
   3628   __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
   3629   result_pos = array_length;  // End of live range for array_length.
   3630   array_length = no_reg;
   3631   __ add(result_pos,
   3632          result,
   3633          Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
   3634 
   3635   // Check the length of the separator.
   3636   __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
   3637   __ cmp(scratch1, Operand(Smi::FromInt(1)));
   3638   __ b(eq, &one_char_separator);
   3639   __ b(gt, &long_separator);
   3640 
   3641   // Empty separator case
   3642   __ bind(&empty_separator_loop);
   3643   // Live values in registers:
   3644   //   result_pos: the position to which we are currently copying characters.
   3645   //   element: Current array element.
   3646   //   elements_end: Array end.
   3647 
   3648   // Copy next array element to the result.
   3649   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
   3650   __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
   3651   __ SmiUntag(string_length);
   3652   __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
   3653   __ CopyBytes(string, result_pos, string_length, scratch1);
   3654   __ cmp(element, elements_end);
   3655   __ b(lt, &empty_separator_loop);  // End while (element < elements_end).
   3656   ASSERT(result.is(r0));
   3657   __ b(&done);
   3658 
   3659   // One-character separator case
   3660   __ bind(&one_char_separator);
   3661   // Replace separator with its ASCII character value.
   3662   __ ldrb(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize));
   3663   // Jump into the loop after the code that copies the separator, so the first
   3664   // element is not preceded by a separator
   3665   __ jmp(&one_char_separator_loop_entry);
   3666 
   3667   __ bind(&one_char_separator_loop);
   3668   // Live values in registers:
   3669   //   result_pos: the position to which we are currently copying characters.
   3670   //   element: Current array element.
   3671   //   elements_end: Array end.
   3672   //   separator: Single separator ASCII char (in lower byte).
   3673 
   3674   // Copy the separator character to the result.
   3675   __ strb(separator, MemOperand(result_pos, 1, PostIndex));
   3676 
   3677   // Copy next array element to the result.
   3678   __ bind(&one_char_separator_loop_entry);
   3679   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
   3680   __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
   3681   __ SmiUntag(string_length);
   3682   __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
   3683   __ CopyBytes(string, result_pos, string_length, scratch1);
   3684   __ cmp(element, elements_end);
   3685   __ b(lt, &one_char_separator_loop);  // End while (element < elements_end).
   3686   ASSERT(result.is(r0));
   3687   __ b(&done);
   3688 
   3689   // Long separator case (separator is more than one character). Entry is at the
   3690   // label long_separator below.
   3691   __ bind(&long_separator_loop);
   3692   // Live values in registers:
   3693   //   result_pos: the position to which we are currently copying characters.
   3694   //   element: Current array element.
   3695   //   elements_end: Array end.
   3696   //   separator: Separator string.
   3697 
   3698   // Copy the separator to the result.
   3699   __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset));
   3700   __ SmiUntag(string_length);
   3701   __ add(string,
   3702          separator,
   3703          Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
   3704   __ CopyBytes(string, result_pos, string_length, scratch1);
   3705 
   3706   __ bind(&long_separator);
   3707   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
   3708   __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
   3709   __ SmiUntag(string_length);
   3710   __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
   3711   __ CopyBytes(string, result_pos, string_length, scratch1);
   3712   __ cmp(element, elements_end);
   3713   __ b(lt, &long_separator_loop);  // End while (element < elements_end).
   3714   ASSERT(result.is(r0));
   3715   __ b(&done);
   3716 
   3717   __ bind(&bailout);
   3718   __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
   3719   __ bind(&done);
   3720   context()->Plug(r0);
   3721 }
   3722 
   3723 
   3724 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   3725   Handle<String> name = expr->name();
   3726   if (name->length() > 0 && name->Get(0) == '_') {
   3727     Comment cmnt(masm_, "[ InlineRuntimeCall");
   3728     EmitInlineRuntimeCall(expr);
   3729     return;
   3730   }
   3731 
   3732   Comment cmnt(masm_, "[ CallRuntime");
   3733   ZoneList<Expression*>* args = expr->arguments();
   3734 
   3735   if (expr->is_jsruntime()) {
   3736     // Prepare for calling JS runtime function.
   3737     __ ldr(r0, GlobalObjectOperand());
   3738     __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
   3739     __ push(r0);
   3740   }
   3741 
   3742   // Push the arguments ("left-to-right").
   3743   int arg_count = args->length();
   3744   for (int i = 0; i < arg_count; i++) {
   3745     VisitForStackValue(args->at(i));
   3746   }
   3747 
   3748   if (expr->is_jsruntime()) {
   3749     // Call the JS runtime function.
   3750     __ mov(r2, Operand(expr->name()));
   3751     RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
   3752     Handle<Code> ic =
   3753         isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
   3754     CallIC(ic, mode, expr->id());
   3755     // Restore context register.
   3756     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   3757   } else {
   3758     // Call the C runtime function.
   3759     __ CallRuntime(expr->function(), arg_count);
   3760   }
   3761   context()->Plug(r0);
   3762 }
   3763 
   3764 
   3765 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
   3766   switch (expr->op()) {
   3767     case Token::DELETE: {
   3768       Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
   3769       Property* property = expr->expression()->AsProperty();
   3770       VariableProxy* proxy = expr->expression()->AsVariableProxy();
   3771 
   3772       if (property != NULL) {
   3773         VisitForStackValue(property->obj());
   3774         VisitForStackValue(property->key());
   3775         StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
   3776             ? kNonStrictMode : kStrictMode;
   3777         __ mov(r1, Operand(Smi::FromInt(strict_mode_flag)));
   3778         __ push(r1);
   3779         __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
   3780         context()->Plug(r0);
   3781       } else if (proxy != NULL) {
   3782         Variable* var = proxy->var();
   3783         // Delete of an unqualified identifier is disallowed in strict mode
   3784         // but "delete this" is allowed.
   3785         ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
   3786         if (var->IsUnallocated()) {
   3787           __ ldr(r2, GlobalObjectOperand());
   3788           __ mov(r1, Operand(var->name()));
   3789           __ mov(r0, Operand(Smi::FromInt(kNonStrictMode)));
   3790           __ Push(r2, r1, r0);
   3791           __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
   3792           context()->Plug(r0);
   3793         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
   3794           // Result of deleting non-global, non-dynamic variables is false.
   3795           // The subexpression does not have side effects.
   3796           context()->Plug(var->is_this());
   3797         } else {
   3798           // Non-global variable.  Call the runtime to try to delete from the
   3799           // context where the variable was introduced.
   3800           __ push(context_register());
   3801           __ mov(r2, Operand(var->name()));
   3802           __ push(r2);
   3803           __ CallRuntime(Runtime::kDeleteContextSlot, 2);
   3804           context()->Plug(r0);
   3805         }
   3806       } else {
   3807         // Result of deleting non-property, non-variable reference is true.
   3808         // The subexpression may have side effects.
   3809         VisitForEffect(expr->expression());
   3810         context()->Plug(true);
   3811       }
   3812       break;
   3813     }
   3814 
   3815     case Token::VOID: {
   3816       Comment cmnt(masm_, "[ UnaryOperation (VOID)");
   3817       VisitForEffect(expr->expression());
   3818       context()->Plug(Heap::kUndefinedValueRootIndex);
   3819       break;
   3820     }
   3821 
   3822     case Token::NOT: {
   3823       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
   3824       if (context()->IsEffect()) {
   3825         // Unary NOT has no side effects so it's only necessary to visit the
   3826         // subexpression.  Match the optimizing compiler by not branching.
   3827         VisitForEffect(expr->expression());
   3828       } else if (context()->IsTest()) {
   3829         const TestContext* test = TestContext::cast(context());
   3830         // The labels are swapped for the recursive call.
   3831         VisitForControl(expr->expression(),
   3832                         test->false_label(),
   3833                         test->true_label(),
   3834                         test->fall_through());
   3835         context()->Plug(test->true_label(), test->false_label());
   3836       } else {
   3837         // We handle value contexts explicitly rather than simply visiting
   3838         // for control and plugging the control flow into the context,
   3839         // because we need to prepare a pair of extra administrative AST ids
   3840         // for the optimizing compiler.
   3841         ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
   3842         Label materialize_true, materialize_false, done;
   3843         VisitForControl(expr->expression(),
   3844                         &materialize_false,
   3845                         &materialize_true,
   3846                         &materialize_true);
   3847         __ bind(&materialize_true);
   3848         PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
   3849         __ LoadRoot(r0, Heap::kTrueValueRootIndex);
   3850         if (context()->IsStackValue()) __ push(r0);
   3851         __ jmp(&done);
   3852         __ bind(&materialize_false);
   3853         PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
   3854         __ LoadRoot(r0, Heap::kFalseValueRootIndex);
   3855         if (context()->IsStackValue()) __ push(r0);
   3856         __ bind(&done);
   3857       }
   3858       break;
   3859     }
   3860 
   3861     case Token::TYPEOF: {
   3862       Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
   3863       { StackValueContext context(this);
   3864         VisitForTypeofValue(expr->expression());
   3865       }
   3866       __ CallRuntime(Runtime::kTypeof, 1);
   3867       context()->Plug(r0);
   3868       break;
   3869     }
   3870 
   3871     case Token::ADD: {
   3872       Comment cmt(masm_, "[ UnaryOperation (ADD)");
   3873       VisitForAccumulatorValue(expr->expression());
   3874       Label no_conversion;
   3875       __ JumpIfSmi(result_register(), &no_conversion);
   3876       ToNumberStub convert_stub;
   3877       __ CallStub(&convert_stub);
   3878       __ bind(&no_conversion);
   3879       context()->Plug(result_register());
   3880       break;
   3881     }
   3882 
   3883     case Token::SUB:
   3884       EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
   3885       break;
   3886 
   3887     case Token::BIT_NOT:
   3888       EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
   3889       break;
   3890 
   3891     default:
   3892       UNREACHABLE();
   3893   }
   3894 }
   3895 
   3896 
   3897 void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
   3898                                            const char* comment) {
   3899   // TODO(svenpanne): Allowing format strings in Comment would be nice here...
   3900   Comment cmt(masm_, comment);
   3901   bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
   3902   UnaryOverwriteMode overwrite =
   3903       can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
   3904   UnaryOpStub stub(expr->op(), overwrite);
   3905   // UnaryOpStub expects the argument to be in the
   3906   // accumulator register r0.
   3907   VisitForAccumulatorValue(expr->expression());
   3908   SetSourcePosition(expr->position());
   3909   CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
   3910   context()->Plug(r0);
   3911 }
   3912 
   3913 
   3914 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
   3915   Comment cmnt(masm_, "[ CountOperation");
   3916   SetSourcePosition(expr->position());
   3917 
   3918   // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
   3919   // as the left-hand side.
   3920   if (!expr->expression()->IsValidLeftHandSide()) {
   3921     VisitForEffect(expr->expression());
   3922     return;
   3923   }
   3924 
   3925   // Expression can only be a property, a global or a (parameter or local)
   3926   // slot.
   3927   enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
   3928   LhsKind assign_type = VARIABLE;
   3929   Property* prop = expr->expression()->AsProperty();
   3930   // In case of a property we use the uninitialized expression context
   3931   // of the key to detect a named property.
   3932   if (prop != NULL) {
   3933     assign_type =
   3934         (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
   3935   }
   3936 
   3937   // Evaluate expression and get value.
   3938   if (assign_type == VARIABLE) {
   3939     ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
   3940     AccumulatorValueContext context(this);
   3941     EmitVariableLoad(expr->expression()->AsVariableProxy());
   3942   } else {
   3943     // Reserve space for result of postfix operation.
   3944     if (expr->is_postfix() && !context()->IsEffect()) {
   3945       __ mov(ip, Operand(Smi::FromInt(0)));
   3946       __ push(ip);
   3947     }
   3948     if (assign_type == NAMED_PROPERTY) {
   3949       // Put the object both on the stack and in the accumulator.
   3950       VisitForAccumulatorValue(prop->obj());
   3951       __ push(r0);
   3952       EmitNamedPropertyLoad(prop);
   3953     } else {
   3954       VisitForStackValue(prop->obj());
   3955       VisitForAccumulatorValue(prop->key());
   3956       __ ldr(r1, MemOperand(sp, 0));
   3957       __ push(r0);
   3958       EmitKeyedPropertyLoad(prop);
   3959     }
   3960   }
   3961 
   3962   // We need a second deoptimization point after loading the value
   3963   // in case evaluating the property load my have a side effect.
   3964   if (assign_type == VARIABLE) {
   3965     PrepareForBailout(expr->expression(), TOS_REG);
   3966   } else {
   3967     PrepareForBailoutForId(expr->CountId(), TOS_REG);
   3968   }
   3969 
   3970   // Call ToNumber only if operand is not a smi.
   3971   Label no_conversion;
   3972   __ JumpIfSmi(r0, &no_conversion);
   3973   ToNumberStub convert_stub;
   3974   __ CallStub(&convert_stub);
   3975   __ bind(&no_conversion);
   3976 
   3977   // Save result for postfix expressions.
   3978   if (expr->is_postfix()) {
   3979     if (!context()->IsEffect()) {
   3980       // Save the result on the stack. If we have a named or keyed property
   3981       // we store the result under the receiver that is currently on top
   3982       // of the stack.
   3983       switch (assign_type) {
   3984         case VARIABLE:
   3985           __ push(r0);
   3986           break;
   3987         case NAMED_PROPERTY:
   3988           __ str(r0, MemOperand(sp, kPointerSize));
   3989           break;
   3990         case KEYED_PROPERTY:
   3991           __ str(r0, MemOperand(sp, 2 * kPointerSize));
   3992           break;
   3993       }
   3994     }
   3995   }
   3996 
   3997 
   3998   // Inline smi case if we are in a loop.
   3999   Label stub_call, done;
   4000   JumpPatchSite patch_site(masm_);
   4001 
   4002   int count_value = expr->op() == Token::INC ? 1 : -1;
   4003   if (ShouldInlineSmiCase(expr->op())) {
   4004     __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
   4005     __ b(vs, &stub_call);
   4006     // We could eliminate this smi check if we split the code at
   4007     // the first smi check before calling ToNumber.
   4008     patch_site.EmitJumpIfSmi(r0, &done);
   4009 
   4010     __ bind(&stub_call);
   4011     // Call stub. Undo operation first.
   4012     __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
   4013   }
   4014   __ mov(r1, Operand(Smi::FromInt(count_value)));
   4015 
   4016   // Record position before stub call.
   4017   SetSourcePosition(expr->position());
   4018 
   4019   BinaryOpStub stub(Token::ADD, NO_OVERWRITE);
   4020   CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
   4021   patch_site.EmitPatchInfo();
   4022   __ bind(&done);
   4023 
   4024   // Store the value returned in r0.
   4025   switch (assign_type) {
   4026     case VARIABLE:
   4027       if (expr->is_postfix()) {
   4028         { EffectContext context(this);
   4029           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
   4030                                  Token::ASSIGN);
   4031           PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
   4032           context.Plug(r0);
   4033         }
   4034         // For all contexts except EffectConstant We have the result on
   4035         // top of the stack.
   4036         if (!context()->IsEffect()) {
   4037           context()->PlugTOS();
   4038         }
   4039       } else {
   4040         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
   4041                                Token::ASSIGN);
   4042         PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
   4043         context()->Plug(r0);
   4044       }
   4045       break;
   4046     case NAMED_PROPERTY: {
   4047       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
   4048       __ pop(r1);
   4049       Handle<Code> ic = is_classic_mode()
   4050           ? isolate()->builtins()->StoreIC_Initialize()
   4051           : isolate()->builtins()->StoreIC_Initialize_Strict();
   4052       CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
   4053       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
   4054       if (expr->is_postfix()) {
   4055         if (!context()->IsEffect()) {
   4056           context()->PlugTOS();
   4057         }
   4058       } else {
   4059         context()->Plug(r0);
   4060       }
   4061       break;
   4062     }
   4063     case KEYED_PROPERTY: {
   4064       __ pop(r1);  // Key.
   4065       __ pop(r2);  // Receiver.
   4066       Handle<Code> ic = is_classic_mode()
   4067           ? isolate()->builtins()->KeyedStoreIC_Initialize()
   4068           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
   4069       CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
   4070       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
   4071       if (expr->is_postfix()) {
   4072         if (!context()->IsEffect()) {
   4073           context()->PlugTOS();
   4074         }
   4075       } else {
   4076         context()->Plug(r0);
   4077       }
   4078       break;
   4079     }
   4080   }
   4081 }
   4082 
   4083 
   4084 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   4085   ASSERT(!context()->IsEffect());
   4086   ASSERT(!context()->IsTest());
   4087   VariableProxy* proxy = expr->AsVariableProxy();
   4088   if (proxy != NULL && proxy->var()->IsUnallocated()) {
   4089     Comment cmnt(masm_, "Global variable");
   4090     __ ldr(r0, GlobalObjectOperand());
   4091     __ mov(r2, Operand(proxy->name()));
   4092     Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   4093     // Use a regular load, not a contextual load, to avoid a reference
   4094     // error.
   4095     CallIC(ic);
   4096     PrepareForBailout(expr, TOS_REG);
   4097     context()->Plug(r0);
   4098   } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
   4099     Label done, slow;
   4100 
   4101     // Generate code for loading from variables potentially shadowed
   4102     // by eval-introduced variables.
   4103     EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
   4104 
   4105     __ bind(&slow);
   4106     __ mov(r0, Operand(proxy->name()));
   4107     __ Push(cp, r0);
   4108     __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
   4109     PrepareForBailout(expr, TOS_REG);
   4110     __ bind(&done);
   4111 
   4112     context()->Plug(r0);
   4113   } else {
   4114     // This expression cannot throw a reference error at the top level.
   4115     VisitInDuplicateContext(expr);
   4116   }
   4117 }
   4118 
   4119 
   4120 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
   4121                                                  Expression* sub_expr,
   4122                                                  Handle<String> check) {
   4123   Label materialize_true, materialize_false;
   4124   Label* if_true = NULL;
   4125   Label* if_false = NULL;
   4126   Label* fall_through = NULL;
   4127   context()->PrepareTest(&materialize_true, &materialize_false,
   4128                          &if_true, &if_false, &fall_through);
   4129 
   4130   { AccumulatorValueContext context(this);
   4131     VisitForTypeofValue(sub_expr);
   4132   }
   4133   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   4134 
   4135   if (check->Equals(isolate()->heap()->number_symbol())) {
   4136     __ JumpIfSmi(r0, if_true);
   4137     __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
   4138     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
   4139     __ cmp(r0, ip);
   4140     Split(eq, if_true, if_false, fall_through);
   4141   } else if (check->Equals(isolate()->heap()->string_symbol())) {
   4142     __ JumpIfSmi(r0, if_false);
   4143     // Check for undetectable objects => false.
   4144     __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
   4145     __ b(ge, if_false);
   4146     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
   4147     __ tst(r1, Operand(1 << Map::kIsUndetectable));
   4148     Split(eq, if_true, if_false, fall_through);
   4149   } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
   4150     __ CompareRoot(r0, Heap::kTrueValueRootIndex);
   4151     __ b(eq, if_true);
   4152     __ CompareRoot(r0, Heap::kFalseValueRootIndex);
   4153     Split(eq, if_true, if_false, fall_through);
   4154   } else if (FLAG_harmony_typeof &&
   4155              check->Equals(isolate()->heap()->null_symbol())) {
   4156     __ CompareRoot(r0, Heap::kNullValueRootIndex);
   4157     Split(eq, if_true, if_false, fall_through);
   4158   } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
   4159     __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
   4160     __ b(eq, if_true);
   4161     __ JumpIfSmi(r0, if_false);
   4162     // Check for undetectable objects => true.
   4163     __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
   4164     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
   4165     __ tst(r1, Operand(1 << Map::kIsUndetectable));
   4166     Split(ne, if_true, if_false, fall_through);
   4167 
   4168   } else if (check->Equals(isolate()->heap()->function_symbol())) {
   4169     __ JumpIfSmi(r0, if_false);
   4170     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
   4171     __ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE);
   4172     __ b(eq, if_true);
   4173     __ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE));
   4174     Split(eq, if_true, if_false, fall_through);
   4175   } else if (check->Equals(isolate()->heap()->object_symbol())) {
   4176     __ JumpIfSmi(r0, if_false);
   4177     if (!FLAG_harmony_typeof) {
   4178       __ CompareRoot(r0, Heap::kNullValueRootIndex);
   4179       __ b(eq, if_true);
   4180     }
   4181     // Check for JS objects => true.
   4182     __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
   4183     __ b(lt, if_false);
   4184     __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
   4185     __ b(gt, if_false);
   4186     // Check for undetectable objects => false.
   4187     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
   4188     __ tst(r1, Operand(1 << Map::kIsUndetectable));
   4189     Split(eq, if_true, if_false, fall_through);
   4190   } else {
   4191     if (if_false != fall_through) __ jmp(if_false);
   4192   }
   4193   context()->Plug(if_true, if_false);
   4194 }
   4195 
   4196 
   4197 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   4198   Comment cmnt(masm_, "[ CompareOperation");
   4199   SetSourcePosition(expr->position());
   4200 
   4201   // First we try a fast inlined version of the compare when one of
   4202   // the operands is a literal.
   4203   if (TryLiteralCompare(expr)) return;
   4204 
   4205   // Always perform the comparison for its control flow.  Pack the result
   4206   // into the expression's context after the comparison is performed.
   4207   Label materialize_true, materialize_false;
   4208   Label* if_true = NULL;
   4209   Label* if_false = NULL;
   4210   Label* fall_through = NULL;
   4211   context()->PrepareTest(&materialize_true, &materialize_false,
   4212                          &if_true, &if_false, &fall_through);
   4213 
   4214   Token::Value op = expr->op();
   4215   VisitForStackValue(expr->left());
   4216   switch (op) {
   4217     case Token::IN:
   4218       VisitForStackValue(expr->right());
   4219       __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
   4220       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
   4221       __ LoadRoot(ip, Heap::kTrueValueRootIndex);
   4222       __ cmp(r0, ip);
   4223       Split(eq, if_true, if_false, fall_through);
   4224       break;
   4225 
   4226     case Token::INSTANCEOF: {
   4227       VisitForStackValue(expr->right());
   4228       InstanceofStub stub(InstanceofStub::kNoFlags);
   4229       __ CallStub(&stub);
   4230       PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   4231       // The stub returns 0 for true.
   4232       __ tst(r0, r0);
   4233       Split(eq, if_true, if_false, fall_through);
   4234       break;
   4235     }
   4236 
   4237     default: {
   4238       VisitForAccumulatorValue(expr->right());
   4239       Condition cond = eq;
   4240       switch (op) {
   4241         case Token::EQ_STRICT:
   4242         case Token::EQ:
   4243           cond = eq;
   4244           break;
   4245         case Token::LT:
   4246           cond = lt;
   4247           break;
   4248         case Token::GT:
   4249           cond = gt;
   4250          break;
   4251         case Token::LTE:
   4252           cond = le;
   4253           break;
   4254         case Token::GTE:
   4255           cond = ge;
   4256           break;
   4257         case Token::IN:
   4258         case Token::INSTANCEOF:
   4259         default:
   4260           UNREACHABLE();
   4261       }
   4262       __ pop(r1);
   4263 
   4264       bool inline_smi_code = ShouldInlineSmiCase(op);
   4265       JumpPatchSite patch_site(masm_);
   4266       if (inline_smi_code) {
   4267         Label slow_case;
   4268         __ orr(r2, r0, Operand(r1));
   4269         patch_site.EmitJumpIfNotSmi(r2, &slow_case);
   4270         __ cmp(r1, r0);
   4271         Split(cond, if_true, if_false, NULL);
   4272         __ bind(&slow_case);
   4273       }
   4274 
   4275       // Record position and call the compare IC.
   4276       SetSourcePosition(expr->position());
   4277       Handle<Code> ic = CompareIC::GetUninitialized(op);
   4278       CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
   4279       patch_site.EmitPatchInfo();
   4280       PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   4281       __ cmp(r0, Operand(0));
   4282       Split(cond, if_true, if_false, fall_through);
   4283     }
   4284   }
   4285 
   4286   // Convert the result of the comparison into one expected for this
   4287   // expression's context.
   4288   context()->Plug(if_true, if_false);
   4289 }
   4290 
   4291 
   4292 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
   4293                                               Expression* sub_expr,
   4294                                               NilValue nil) {
   4295   Label materialize_true, materialize_false;
   4296   Label* if_true = NULL;
   4297   Label* if_false = NULL;
   4298   Label* fall_through = NULL;
   4299   context()->PrepareTest(&materialize_true, &materialize_false,
   4300                          &if_true, &if_false, &fall_through);
   4301 
   4302   VisitForAccumulatorValue(sub_expr);
   4303   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   4304   Heap::RootListIndex nil_value = nil == kNullValue ?
   4305       Heap::kNullValueRootIndex :
   4306       Heap::kUndefinedValueRootIndex;
   4307   __ LoadRoot(r1, nil_value);
   4308   __ cmp(r0, r1);
   4309   if (expr->op() == Token::EQ_STRICT) {
   4310     Split(eq, if_true, if_false, fall_through);
   4311   } else {
   4312     Heap::RootListIndex other_nil_value = nil == kNullValue ?
   4313         Heap::kUndefinedValueRootIndex :
   4314         Heap::kNullValueRootIndex;
   4315     __ b(eq, if_true);
   4316     __ LoadRoot(r1, other_nil_value);
   4317     __ cmp(r0, r1);
   4318     __ b(eq, if_true);
   4319     __ JumpIfSmi(r0, if_false);
   4320     // It can be an undetectable object.
   4321     __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
   4322     __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
   4323     __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
   4324     __ cmp(r1, Operand(1 << Map::kIsUndetectable));
   4325     Split(eq, if_true, if_false, fall_through);
   4326   }
   4327   context()->Plug(if_true, if_false);
   4328 }
   4329 
   4330 
   4331 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   4332   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   4333   context()->Plug(r0);
   4334 }
   4335 
   4336 
   4337 Register FullCodeGenerator::result_register() {
   4338   return r0;
   4339 }
   4340 
   4341 
   4342 Register FullCodeGenerator::context_register() {
   4343   return cp;
   4344 }
   4345 
   4346 
   4347 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
   4348   ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
   4349   __ str(value, MemOperand(fp, frame_offset));
   4350 }
   4351 
   4352 
   4353 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
   4354   __ ldr(dst, ContextOperand(cp, context_index));
   4355 }
   4356 
   4357 
   4358 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
   4359   Scope* declaration_scope = scope()->DeclarationScope();
   4360   if (declaration_scope->is_global_scope()) {
   4361     // Contexts nested in the global context have a canonical empty function
   4362     // as their closure, not the anonymous closure containing the global
   4363     // code.  Pass a smi sentinel and let the runtime look up the empty
   4364     // function.
   4365     __ mov(ip, Operand(Smi::FromInt(0)));
   4366   } else if (declaration_scope->is_eval_scope()) {
   4367     // Contexts created by a call to eval have the same closure as the
   4368     // context calling eval, not the anonymous closure containing the eval
   4369     // code.  Fetch it from the context.
   4370     __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX));
   4371   } else {
   4372     ASSERT(declaration_scope->is_function_scope());
   4373     __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   4374   }
   4375   __ push(ip);
   4376 }
   4377 
   4378 
   4379 // ----------------------------------------------------------------------------
   4380 // Non-local control flow support.
   4381 
   4382 void FullCodeGenerator::EnterFinallyBlock() {
   4383   ASSERT(!result_register().is(r1));
   4384   // Store result register while executing finally block.
   4385   __ push(result_register());
   4386   // Cook return address in link register to stack (smi encoded Code* delta)
   4387   __ sub(r1, lr, Operand(masm_->CodeObject()));
   4388   ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
   4389   STATIC_ASSERT(kSmiTag == 0);
   4390   __ add(r1, r1, Operand(r1));  // Convert to smi.
   4391   __ push(r1);
   4392 }
   4393 
   4394 
   4395 void FullCodeGenerator::ExitFinallyBlock() {
   4396   ASSERT(!result_register().is(r1));
   4397   // Restore result register from stack.
   4398   __ pop(r1);
   4399   // Uncook return address and return.
   4400   __ pop(result_register());
   4401   ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
   4402   __ mov(r1, Operand(r1, ASR, 1));  // Un-smi-tag value.
   4403   __ add(pc, r1, Operand(masm_->CodeObject()));
   4404 }
   4405 
   4406 
   4407 #undef __
   4408 
   4409 #define __ ACCESS_MASM(masm())
   4410 
   4411 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
   4412     int* stack_depth,
   4413     int* context_length) {
   4414   // The macros used here must preserve the result register.
   4415 
   4416   // Because the handler block contains the context of the finally
   4417   // code, we can restore it directly from there for the finally code
   4418   // rather than iteratively unwinding contexts via their previous
   4419   // links.
   4420   __ Drop(*stack_depth);  // Down to the handler block.
   4421   if (*context_length > 0) {
   4422     // Restore the context to its dedicated register and the stack.
   4423     __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
   4424     __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   4425   }
   4426   __ PopTryHandler();
   4427   __ bl(finally_entry_);
   4428 
   4429   *stack_depth = 0;
   4430   *context_length = 0;
   4431   return previous_;
   4432 }
   4433 
   4434 
   4435 #undef __
   4436 
   4437 } }  // namespace v8::internal
   4438 
   4439 #endif  // V8_TARGET_ARCH_ARM
   4440