Home | History | Annotate | Download | only in mips
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #if V8_TARGET_ARCH_MIPS
      6 
      7 // Note on Mips implementation:
      8 //
      9 // The result_register() for mips is the 'v0' register, which is defined
     10 // by the ABI to contain function return values. However, the first
     11 // parameter to a function is defined to be 'a0'. So there are many
     12 // places where we have to move a previous result in v0 to a0 for the
     13 // next call: mov(a0, v0). This is not needed on the other architectures.
     14 
     15 #include "src/full-codegen/full-codegen.h"
     16 #include "src/ast/compile-time-value.h"
     17 #include "src/ast/scopes.h"
     18 #include "src/code-factory.h"
     19 #include "src/code-stubs.h"
     20 #include "src/codegen.h"
     21 #include "src/compilation-info.h"
     22 #include "src/compiler.h"
     23 #include "src/debug/debug.h"
     24 #include "src/ic/ic.h"
     25 
     26 #include "src/mips/code-stubs-mips.h"
     27 #include "src/mips/macro-assembler-mips.h"
     28 
     29 namespace v8 {
     30 namespace internal {
     31 
     32 #define __ ACCESS_MASM(masm())
     33 
     34 // A patch site is a location in the code which it is possible to patch. This
     35 // class has a number of methods to emit the code which is patchable and the
     36 // method EmitPatchInfo to record a marker back to the patchable code. This
     37 // marker is a andi zero_reg, rx, #yyyy instruction, and rx * 0x0000ffff + yyyy
     38 // (raw 16 bit immediate value is used) is the delta from the pc to the first
     39 // instruction of the patchable code.
     40 // The marker instruction is effectively a NOP (dest is zero_reg) and will
     41 // never be emitted by normal code.
     42 class JumpPatchSite BASE_EMBEDDED {
     43  public:
     44   explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
     45 #ifdef DEBUG
     46     info_emitted_ = false;
     47 #endif
     48   }
     49 
     50   ~JumpPatchSite() {
     51     DCHECK(patch_site_.is_bound() == info_emitted_);
     52   }
     53 
     54   // When initially emitting this ensure that a jump is always generated to skip
     55   // the inlined smi code.
     56   void EmitJumpIfNotSmi(Register reg, Label* target) {
     57     DCHECK(!patch_site_.is_bound() && !info_emitted_);
     58     Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
     59     __ bind(&patch_site_);
     60     __ andi(at, reg, 0);
     61     // Always taken before patched.
     62     __ BranchShort(target, eq, at, Operand(zero_reg));
     63   }
     64 
     65   // When initially emitting this ensure that a jump is never generated to skip
     66   // the inlined smi code.
     67   void EmitJumpIfSmi(Register reg, Label* target) {
     68     Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
     69     DCHECK(!patch_site_.is_bound() && !info_emitted_);
     70     __ bind(&patch_site_);
     71     __ andi(at, reg, 0);
     72     // Never taken before patched.
     73     __ BranchShort(target, ne, at, Operand(zero_reg));
     74   }
     75 
     76   void EmitPatchInfo() {
     77     if (patch_site_.is_bound()) {
     78       int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
     79       Register reg = Register::from_code(delta_to_patch_site / kImm16Mask);
     80       __ andi(zero_reg, reg, delta_to_patch_site % kImm16Mask);
     81 #ifdef DEBUG
     82       info_emitted_ = true;
     83 #endif
     84     } else {
     85       __ nop();  // Signals no inlined code.
     86     }
     87   }
     88 
     89  private:
     90   MacroAssembler* masm() { return masm_; }
     91   MacroAssembler* masm_;
     92   Label patch_site_;
     93 #ifdef DEBUG
     94   bool info_emitted_;
     95 #endif
     96 };
     97 
     98 
     99 // Generate code for a JS function.  On entry to the function the receiver
    100 // and arguments have been pushed on the stack left to right.  The actual
    101 // argument count matches the formal parameter count expected by the
    102 // function.
    103 //
    104 // The live registers are:
    105 //   o a1: the JS function object being called (i.e. ourselves)
    106 //   o a3: the new target value
    107 //   o cp: our context
    108 //   o fp: our caller's frame pointer
    109 //   o sp: stack pointer
    110 //   o ra: return address
    111 //
    112 // The function builds a JS frame.  Please see JavaScriptFrameConstants in
    113 // frames-mips.h for its layout.
    114 void FullCodeGenerator::Generate() {
    115   CompilationInfo* info = info_;
    116   profiling_counter_ = isolate()->factory()->NewCell(
    117       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
    118   SetFunctionPosition(literal());
    119   Comment cmnt(masm_, "[ function compiled by full code generator");
    120 
    121   ProfileEntryHookStub::MaybeCallEntryHook(masm_);
    122 
    123   if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
    124     int receiver_offset = info->scope()->num_parameters() * kPointerSize;
    125     __ lw(a2, MemOperand(sp, receiver_offset));
    126     __ AssertNotSmi(a2);
    127     __ GetObjectType(a2, a2, a2);
    128     __ Check(ge, kSloppyFunctionExpectsJSReceiverReceiver, a2,
    129              Operand(FIRST_JS_RECEIVER_TYPE));
    130   }
    131 
    132   // Open a frame scope to indicate that there is a frame on the stack.  The
    133   // MANUAL indicates that the scope shouldn't actually generate code to set up
    134   // the frame (that is done below).
    135   FrameScope frame_scope(masm_, StackFrame::MANUAL);
    136 
    137   info->set_prologue_offset(masm_->pc_offset());
    138   __ Prologue(info->GeneratePreagedPrologue());
    139 
    140   // Increment invocation count for the function.
    141   {
    142     Comment cmnt(masm_, "[ Increment invocation count");
    143     __ lw(a0, FieldMemOperand(a1, JSFunction::kLiteralsOffset));
    144     __ lw(a0, FieldMemOperand(a0, LiteralsArray::kFeedbackVectorOffset));
    145     __ lw(t0, FieldMemOperand(
    146                   a0, TypeFeedbackVector::kInvocationCountIndex * kPointerSize +
    147                           TypeFeedbackVector::kHeaderSize));
    148     __ Addu(t0, t0, Operand(Smi::FromInt(1)));
    149     __ sw(t0, FieldMemOperand(
    150                   a0, TypeFeedbackVector::kInvocationCountIndex * kPointerSize +
    151                           TypeFeedbackVector::kHeaderSize));
    152   }
    153 
    154   { Comment cmnt(masm_, "[ Allocate locals");
    155     int locals_count = info->scope()->num_stack_slots();
    156     // Generators allocate locals, if any, in context slots.
    157     DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0);
    158     OperandStackDepthIncrement(locals_count);
    159     if (locals_count > 0) {
    160       if (locals_count >= 128) {
    161         Label ok;
    162         __ Subu(t5, sp, Operand(locals_count * kPointerSize));
    163         __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
    164         __ Branch(&ok, hs, t5, Operand(a2));
    165         __ CallRuntime(Runtime::kThrowStackOverflow);
    166         __ bind(&ok);
    167       }
    168       __ LoadRoot(t5, Heap::kUndefinedValueRootIndex);
    169       int kMaxPushes = FLAG_optimize_for_size ? 4 : 32;
    170       if (locals_count >= kMaxPushes) {
    171         int loop_iterations = locals_count / kMaxPushes;
    172         __ li(a2, Operand(loop_iterations));
    173         Label loop_header;
    174         __ bind(&loop_header);
    175         // Do pushes.
    176         __ Subu(sp, sp, Operand(kMaxPushes * kPointerSize));
    177         for (int i = 0; i < kMaxPushes; i++) {
    178           __ sw(t5, MemOperand(sp, i * kPointerSize));
    179         }
    180         // Continue loop if not done.
    181         __ Subu(a2, a2, Operand(1));
    182         __ Branch(&loop_header, ne, a2, Operand(zero_reg));
    183       }
    184       int remaining = locals_count % kMaxPushes;
    185       // Emit the remaining pushes.
    186       __ Subu(sp, sp, Operand(remaining * kPointerSize));
    187       for (int i  = 0; i < remaining; i++) {
    188         __ sw(t5, MemOperand(sp, i * kPointerSize));
    189       }
    190     }
    191   }
    192 
    193   bool function_in_register_a1 = true;
    194 
    195   // Possibly allocate a local context.
    196   if (info->scope()->NeedsContext()) {
    197     Comment cmnt(masm_, "[ Allocate context");
    198     // Argument to NewContext is the function, which is still in a1.
    199     bool need_write_barrier = true;
    200     int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
    201     if (info->scope()->is_script_scope()) {
    202       __ push(a1);
    203       __ Push(info->scope()->scope_info());
    204       __ CallRuntime(Runtime::kNewScriptContext);
    205       PrepareForBailoutForId(BailoutId::ScriptContext(),
    206                              BailoutState::TOS_REGISTER);
    207       // The new target value is not used, clobbering is safe.
    208       DCHECK_NULL(info->scope()->new_target_var());
    209     } else {
    210       if (info->scope()->new_target_var() != nullptr) {
    211         __ push(a3);  // Preserve new target.
    212       }
    213       if (slots <= FastNewFunctionContextStub::kMaximumSlots) {
    214         FastNewFunctionContextStub stub(isolate());
    215         __ li(FastNewFunctionContextDescriptor::SlotsRegister(),
    216               Operand(slots));
    217         __ CallStub(&stub);
    218         // Result of FastNewFunctionContextStub is always in new space.
    219         need_write_barrier = false;
    220       } else {
    221         __ push(a1);
    222         __ CallRuntime(Runtime::kNewFunctionContext);
    223       }
    224       if (info->scope()->new_target_var() != nullptr) {
    225         __ pop(a3);  // Restore new target.
    226       }
    227     }
    228     function_in_register_a1 = false;
    229     // Context is returned in v0. It replaces the context passed to us.
    230     // It's saved in the stack and kept live in cp.
    231     __ mov(cp, v0);
    232     __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
    233     // Copy any necessary parameters into the context.
    234     int num_parameters = info->scope()->num_parameters();
    235     int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
    236     for (int i = first_parameter; i < num_parameters; i++) {
    237       Variable* var =
    238           (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i);
    239       if (var->IsContextSlot()) {
    240         int parameter_offset = StandardFrameConstants::kCallerSPOffset +
    241                                  (num_parameters - 1 - i) * kPointerSize;
    242         // Load parameter from stack.
    243         __ lw(a0, MemOperand(fp, parameter_offset));
    244         // Store it in the context.
    245         MemOperand target = ContextMemOperand(cp, var->index());
    246         __ sw(a0, target);
    247 
    248         // Update the write barrier.
    249         if (need_write_barrier) {
    250           __ RecordWriteContextSlot(cp, target.offset(), a0, a2,
    251                                     kRAHasBeenSaved, kDontSaveFPRegs);
    252         } else if (FLAG_debug_code) {
    253           Label done;
    254           __ JumpIfInNewSpace(cp, a0, &done);
    255           __ Abort(kExpectedNewSpaceObject);
    256           __ bind(&done);
    257         }
    258       }
    259     }
    260   }
    261 
    262   // Register holding this function and new target are both trashed in case we
    263   // bailout here. But since that can happen only when new target is not used
    264   // and we allocate a context, the value of |function_in_register| is correct.
    265   PrepareForBailoutForId(BailoutId::FunctionContext(),
    266                          BailoutState::NO_REGISTERS);
    267 
    268   // Possibly set up a local binding to the this function which is used in
    269   // derived constructors with super calls.
    270   Variable* this_function_var = info->scope()->this_function_var();
    271   if (this_function_var != nullptr) {
    272     Comment cmnt(masm_, "[ This function");
    273     if (!function_in_register_a1) {
    274       __ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
    275       // The write barrier clobbers register again, keep it marked as such.
    276     }
    277     SetVar(this_function_var, a1, a0, a2);
    278   }
    279 
    280   // Possibly set up a local binding to the new target value.
    281   Variable* new_target_var = info->scope()->new_target_var();
    282   if (new_target_var != nullptr) {
    283     Comment cmnt(masm_, "[ new.target");
    284     SetVar(new_target_var, a3, a0, a2);
    285   }
    286 
    287   // Possibly allocate RestParameters
    288   Variable* rest_param = info->scope()->rest_parameter();
    289   if (rest_param != nullptr) {
    290     Comment cmnt(masm_, "[ Allocate rest parameter array");
    291     if (!function_in_register_a1) {
    292       __ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
    293     }
    294     FastNewRestParameterStub stub(isolate());
    295     __ CallStub(&stub);
    296     function_in_register_a1 = false;
    297     SetVar(rest_param, v0, a1, a2);
    298   }
    299 
    300   Variable* arguments = info->scope()->arguments();
    301   if (arguments != NULL) {
    302     // Function uses arguments object.
    303     Comment cmnt(masm_, "[ Allocate arguments object");
    304     if (!function_in_register_a1) {
    305       // Load this again, if it's used by the local context below.
    306       __ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
    307     }
    308     if (is_strict(language_mode()) || !has_simple_parameters()) {
    309       FastNewStrictArgumentsStub stub(isolate());
    310       __ CallStub(&stub);
    311     } else if (literal()->has_duplicate_parameters()) {
    312       __ Push(a1);
    313       __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
    314     } else {
    315       FastNewSloppyArgumentsStub stub(isolate());
    316       __ CallStub(&stub);
    317     }
    318 
    319     SetVar(arguments, v0, a1, a2);
    320   }
    321 
    322   if (FLAG_trace) {
    323     __ CallRuntime(Runtime::kTraceEnter);
    324   }
    325 
    326   // Visit the declarations and body unless there is an illegal
    327   // redeclaration.
    328   PrepareForBailoutForId(BailoutId::FunctionEntry(),
    329                          BailoutState::NO_REGISTERS);
    330   {
    331     Comment cmnt(masm_, "[ Declarations");
    332     VisitDeclarations(scope()->declarations());
    333   }
    334 
    335   // Assert that the declarations do not use ICs. Otherwise the debugger
    336   // won't be able to redirect a PC at an IC to the correct IC in newly
    337   // recompiled code.
    338   DCHECK_EQ(0, ic_total_count_);
    339 
    340   {
    341     Comment cmnt(masm_, "[ Stack check");
    342     PrepareForBailoutForId(BailoutId::Declarations(),
    343                            BailoutState::NO_REGISTERS);
    344     Label ok;
    345     __ LoadRoot(at, Heap::kStackLimitRootIndex);
    346     __ Branch(&ok, hs, sp, Operand(at));
    347     Handle<Code> stack_check = isolate()->builtins()->StackCheck();
    348     PredictableCodeSizeScope predictable(
    349         masm_, masm_->CallSize(stack_check, RelocInfo::CODE_TARGET));
    350     __ Call(stack_check, RelocInfo::CODE_TARGET);
    351     __ bind(&ok);
    352   }
    353 
    354   {
    355     Comment cmnt(masm_, "[ Body");
    356     DCHECK(loop_depth() == 0);
    357     VisitStatements(literal()->body());
    358     DCHECK(loop_depth() == 0);
    359   }
    360 
    361   // Always emit a 'return undefined' in case control fell off the end of
    362   // the body.
    363   { Comment cmnt(masm_, "[ return <undefined>;");
    364     __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
    365   }
    366   EmitReturnSequence();
    367 }
    368 
    369 
    370 void FullCodeGenerator::ClearAccumulator() {
    371   DCHECK(Smi::kZero == 0);
    372   __ mov(v0, zero_reg);
    373 }
    374 
    375 
    376 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
    377   __ li(a2, Operand(profiling_counter_));
    378   __ lw(a3, FieldMemOperand(a2, Cell::kValueOffset));
    379   __ Subu(a3, a3, Operand(Smi::FromInt(delta)));
    380   __ sw(a3, FieldMemOperand(a2, Cell::kValueOffset));
    381 }
    382 
    383 
    384 void FullCodeGenerator::EmitProfilingCounterReset() {
    385   int reset_value = FLAG_interrupt_budget;
    386   if (info_->is_debug()) {
    387     // Detect debug break requests as soon as possible.
    388     reset_value = FLAG_interrupt_budget >> 4;
    389   }
    390   __ li(a2, Operand(profiling_counter_));
    391   __ li(a3, Operand(Smi::FromInt(reset_value)));
    392   __ sw(a3, FieldMemOperand(a2, Cell::kValueOffset));
    393 }
    394 
    395 
    396 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
    397                                                 Label* back_edge_target) {
    398   // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need
    399   // to make sure it is constant. Branch may emit a skip-or-jump sequence
    400   // instead of the normal Branch. It seems that the "skip" part of that
    401   // sequence is about as long as this Branch would be so it is safe to ignore
    402   // that.
    403   Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
    404   Comment cmnt(masm_, "[ Back edge bookkeeping");
    405   Label ok;
    406   DCHECK(back_edge_target->is_bound());
    407   int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
    408   int weight = Min(kMaxBackEdgeWeight,
    409                    Max(1, distance / kCodeSizeMultiplier));
    410   EmitProfilingCounterDecrement(weight);
    411   __ slt(at, a3, zero_reg);
    412   __ beq(at, zero_reg, &ok);
    413   // Call will emit a li t9 first, so it is safe to use the delay slot.
    414   __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
    415   // Record a mapping of this PC offset to the OSR id.  This is used to find
    416   // the AST id from the unoptimized code in order to use it as a key into
    417   // the deoptimization input data found in the optimized code.
    418   RecordBackEdge(stmt->OsrEntryId());
    419   EmitProfilingCounterReset();
    420 
    421   __ bind(&ok);
    422   PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
    423   // Record a mapping of the OSR id to this PC.  This is used if the OSR
    424   // entry becomes the target of a bailout.  We don't expect it to be, but
    425   // we want it to work if it is.
    426   PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
    427 }
    428 
    429 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
    430     bool is_tail_call) {
    431   // Pretend that the exit is a backwards jump to the entry.
    432   int weight = 1;
    433   if (info_->ShouldSelfOptimize()) {
    434     weight = FLAG_interrupt_budget / FLAG_self_opt_count;
    435   } else {
    436     int distance = masm_->pc_offset();
    437     weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
    438   }
    439   EmitProfilingCounterDecrement(weight);
    440   Label ok;
    441   __ Branch(&ok, ge, a3, Operand(zero_reg));
    442   // Don't need to save result register if we are going to do a tail call.
    443   if (!is_tail_call) {
    444     __ push(v0);
    445   }
    446   __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
    447   if (!is_tail_call) {
    448     __ pop(v0);
    449   }
    450   EmitProfilingCounterReset();
    451   __ bind(&ok);
    452 }
    453 
    454 void FullCodeGenerator::EmitReturnSequence() {
    455   Comment cmnt(masm_, "[ Return sequence");
    456   if (return_label_.is_bound()) {
    457     __ Branch(&return_label_);
    458   } else {
    459     __ bind(&return_label_);
    460     if (FLAG_trace) {
    461       // Push the return value on the stack as the parameter.
    462       // Runtime::TraceExit returns its parameter in v0.
    463       __ push(v0);
    464       __ CallRuntime(Runtime::kTraceExit);
    465     }
    466     EmitProfilingCounterHandlingForReturnSequence(false);
    467 
    468     // Make sure that the constant pool is not emitted inside of the return
    469     // sequence.
    470     { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
    471       int32_t arg_count = info_->scope()->num_parameters() + 1;
    472       int32_t sp_delta = arg_count * kPointerSize;
    473       SetReturnPosition(literal());
    474       __ mov(sp, fp);
    475       __ MultiPop(static_cast<RegList>(fp.bit() | ra.bit()));
    476       __ Addu(sp, sp, Operand(sp_delta));
    477       __ Jump(ra);
    478     }
    479   }
    480 }
    481 
    482 void FullCodeGenerator::RestoreContext() {
    483   __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
    484 }
    485 
    486 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
    487   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
    488   codegen()->GetVar(result_register(), var);
    489   codegen()->PushOperand(result_register());
    490 }
    491 
    492 
    493 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
    494 }
    495 
    496 
    497 void FullCodeGenerator::AccumulatorValueContext::Plug(
    498     Heap::RootListIndex index) const {
    499   __ LoadRoot(result_register(), index);
    500 }
    501 
    502 
    503 void FullCodeGenerator::StackValueContext::Plug(
    504     Heap::RootListIndex index) const {
    505   __ LoadRoot(result_register(), index);
    506   codegen()->PushOperand(result_register());
    507 }
    508 
    509 
    510 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
    511   codegen()->PrepareForBailoutBeforeSplit(condition(),
    512                                           true,
    513                                           true_label_,
    514                                           false_label_);
    515   if (index == Heap::kUndefinedValueRootIndex ||
    516       index == Heap::kNullValueRootIndex ||
    517       index == Heap::kFalseValueRootIndex) {
    518     if (false_label_ != fall_through_) __ Branch(false_label_);
    519   } else if (index == Heap::kTrueValueRootIndex) {
    520     if (true_label_ != fall_through_) __ Branch(true_label_);
    521   } else {
    522     __ LoadRoot(result_register(), index);
    523     codegen()->DoTest(this);
    524   }
    525 }
    526 
    527 
    528 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
    529 }
    530 
    531 
    532 void FullCodeGenerator::AccumulatorValueContext::Plug(
    533     Handle<Object> lit) const {
    534   __ li(result_register(), Operand(lit));
    535 }
    536 
    537 
    538 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
    539   // Immediates cannot be pushed directly.
    540   __ li(result_register(), Operand(lit));
    541   codegen()->PushOperand(result_register());
    542 }
    543 
    544 
    545 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
    546   codegen()->PrepareForBailoutBeforeSplit(condition(),
    547                                           true,
    548                                           true_label_,
    549                                           false_label_);
    550   DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
    551          !lit->IsUndetectable());
    552   if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
    553       lit->IsFalse(isolate())) {
    554     if (false_label_ != fall_through_) __ Branch(false_label_);
    555   } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
    556     if (true_label_ != fall_through_) __ Branch(true_label_);
    557   } else if (lit->IsString()) {
    558     if (String::cast(*lit)->length() == 0) {
    559       if (false_label_ != fall_through_) __ Branch(false_label_);
    560     } else {
    561       if (true_label_ != fall_through_) __ Branch(true_label_);
    562     }
    563   } else if (lit->IsSmi()) {
    564     if (Smi::cast(*lit)->value() == 0) {
    565       if (false_label_ != fall_through_) __ Branch(false_label_);
    566     } else {
    567       if (true_label_ != fall_through_) __ Branch(true_label_);
    568     }
    569   } else {
    570     // For simplicity we always test the accumulator register.
    571     __ li(result_register(), Operand(lit));
    572     codegen()->DoTest(this);
    573   }
    574 }
    575 
    576 
    577 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
    578                                                        Register reg) const {
    579   DCHECK(count > 0);
    580   if (count > 1) codegen()->DropOperands(count - 1);
    581   __ sw(reg, MemOperand(sp, 0));
    582 }
    583 
    584 
    585 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
    586                                             Label* materialize_false) const {
    587   DCHECK(materialize_true == materialize_false);
    588   __ bind(materialize_true);
    589 }
    590 
    591 
    592 void FullCodeGenerator::AccumulatorValueContext::Plug(
    593     Label* materialize_true,
    594     Label* materialize_false) const {
    595   Label done;
    596   __ bind(materialize_true);
    597   __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
    598   __ Branch(&done);
    599   __ bind(materialize_false);
    600   __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
    601   __ bind(&done);
    602 }
    603 
    604 
    605 void FullCodeGenerator::StackValueContext::Plug(
    606     Label* materialize_true,
    607     Label* materialize_false) const {
    608   codegen()->OperandStackDepthIncrement(1);
    609   Label done;
    610   __ bind(materialize_true);
    611   __ LoadRoot(at, Heap::kTrueValueRootIndex);
    612   // Push the value as the following branch can clobber at in long branch mode.
    613   __ push(at);
    614   __ Branch(&done);
    615   __ bind(materialize_false);
    616   __ LoadRoot(at, Heap::kFalseValueRootIndex);
    617   __ push(at);
    618   __ bind(&done);
    619 }
    620 
    621 
    622 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
    623                                           Label* materialize_false) const {
    624   DCHECK(materialize_true == true_label_);
    625   DCHECK(materialize_false == false_label_);
    626 }
    627 
    628 
    629 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
    630   Heap::RootListIndex value_root_index =
    631       flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
    632   __ LoadRoot(result_register(), value_root_index);
    633 }
    634 
    635 
    636 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
    637   Heap::RootListIndex value_root_index =
    638       flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
    639   __ LoadRoot(at, value_root_index);
    640   codegen()->PushOperand(at);
    641 }
    642 
    643 
    644 void FullCodeGenerator::TestContext::Plug(bool flag) const {
    645   codegen()->PrepareForBailoutBeforeSplit(condition(),
    646                                           true,
    647                                           true_label_,
    648                                           false_label_);
    649   if (flag) {
    650     if (true_label_ != fall_through_) __ Branch(true_label_);
    651   } else {
    652     if (false_label_ != fall_through_) __ Branch(false_label_);
    653   }
    654 }
    655 
    656 
    657 void FullCodeGenerator::DoTest(Expression* condition,
    658                                Label* if_true,
    659                                Label* if_false,
    660                                Label* fall_through) {
    661   __ mov(a0, result_register());
    662   Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
    663   CallIC(ic, condition->test_id());
    664   __ LoadRoot(at, Heap::kTrueValueRootIndex);
    665   Split(eq, result_register(), Operand(at), if_true, if_false, fall_through);
    666 }
    667 
    668 
    669 void FullCodeGenerator::Split(Condition cc,
    670                               Register lhs,
    671                               const Operand&  rhs,
    672                               Label* if_true,
    673                               Label* if_false,
    674                               Label* fall_through) {
    675   if (if_false == fall_through) {
    676     __ Branch(if_true, cc, lhs, rhs);
    677   } else if (if_true == fall_through) {
    678     __ Branch(if_false, NegateCondition(cc), lhs, rhs);
    679   } else {
    680     __ Branch(if_true, cc, lhs, rhs);
    681     __ Branch(if_false);
    682   }
    683 }
    684 
    685 
    686 MemOperand FullCodeGenerator::StackOperand(Variable* var) {
    687   DCHECK(var->IsStackAllocated());
    688   // Offset is negative because higher indexes are at lower addresses.
    689   int offset = -var->index() * kPointerSize;
    690   // Adjust by a (parameter or local) base offset.
    691   if (var->IsParameter()) {
    692     offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
    693   } else {
    694     offset += JavaScriptFrameConstants::kLocal0Offset;
    695   }
    696   return MemOperand(fp, offset);
    697 }
    698 
    699 
    700 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
    701   DCHECK(var->IsContextSlot() || var->IsStackAllocated());
    702   if (var->IsContextSlot()) {
    703     int context_chain_length = scope()->ContextChainLength(var->scope());
    704     __ LoadContext(scratch, context_chain_length);
    705     return ContextMemOperand(scratch, var->index());
    706   } else {
    707     return StackOperand(var);
    708   }
    709 }
    710 
    711 
    712 void FullCodeGenerator::GetVar(Register dest, Variable* var) {
    713   // Use destination as scratch.
    714   MemOperand location = VarOperand(var, dest);
    715   __ lw(dest, location);
    716 }
    717 
    718 
    719 void FullCodeGenerator::SetVar(Variable* var,
    720                                Register src,
    721                                Register scratch0,
    722                                Register scratch1) {
    723   DCHECK(var->IsContextSlot() || var->IsStackAllocated());
    724   DCHECK(!scratch0.is(src));
    725   DCHECK(!scratch0.is(scratch1));
    726   DCHECK(!scratch1.is(src));
    727   MemOperand location = VarOperand(var, scratch0);
    728   __ sw(src, location);
    729   // Emit the write barrier code if the location is in the heap.
    730   if (var->IsContextSlot()) {
    731     __ RecordWriteContextSlot(scratch0,
    732                               location.offset(),
    733                               src,
    734                               scratch1,
    735                               kRAHasBeenSaved,
    736                               kDontSaveFPRegs);
    737   }
    738 }
    739 
    740 
    741 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
    742                                                      bool should_normalize,
    743                                                      Label* if_true,
    744                                                      Label* if_false) {
    745   // Only prepare for bailouts before splits if we're in a test
    746   // context. Otherwise, we let the Visit function deal with the
    747   // preparation to avoid preparing with the same AST id twice.
    748   if (!context()->IsTest()) return;
    749 
    750   Label skip;
    751   if (should_normalize) __ Branch(&skip);
    752   PrepareForBailout(expr, BailoutState::TOS_REGISTER);
    753   if (should_normalize) {
    754     __ LoadRoot(t0, Heap::kTrueValueRootIndex);
    755     Split(eq, v0, Operand(t0), if_true, if_false, NULL);
    756     __ bind(&skip);
    757   }
    758 }
    759 
    760 
    761 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
    762   // The variable in the declaration always resides in the current function
    763   // context.
    764   DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
    765   if (FLAG_debug_code) {
    766     // Check that we're not inside a with or catch context.
    767     __ lw(a1, FieldMemOperand(cp, HeapObject::kMapOffset));
    768     __ LoadRoot(t0, Heap::kWithContextMapRootIndex);
    769     __ Check(ne, kDeclarationInWithContext,
    770         a1, Operand(t0));
    771     __ LoadRoot(t0, Heap::kCatchContextMapRootIndex);
    772     __ Check(ne, kDeclarationInCatchContext,
    773         a1, Operand(t0));
    774   }
    775 }
    776 
    777 
    778 void FullCodeGenerator::VisitVariableDeclaration(
    779     VariableDeclaration* declaration) {
    780   VariableProxy* proxy = declaration->proxy();
    781   Variable* variable = proxy->var();
    782   switch (variable->location()) {
    783     case VariableLocation::UNALLOCATED: {
    784       DCHECK(!variable->binding_needs_init());
    785       FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
    786       DCHECK(!slot.IsInvalid());
    787       globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
    788       globals_->Add(isolate()->factory()->undefined_value(), zone());
    789       break;
    790     }
    791     case VariableLocation::PARAMETER:
    792     case VariableLocation::LOCAL:
    793       if (variable->binding_needs_init()) {
    794         Comment cmnt(masm_, "[ VariableDeclaration");
    795         __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
    796         __ sw(t0, StackOperand(variable));
    797       }
    798       break;
    799 
    800     case VariableLocation::CONTEXT:
    801       if (variable->binding_needs_init()) {
    802         Comment cmnt(masm_, "[ VariableDeclaration");
    803         EmitDebugCheckDeclarationContext(variable);
    804           __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
    805           __ sw(at, ContextMemOperand(cp, variable->index()));
    806           // No write barrier since the_hole_value is in old space.
    807           PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
    808       }
    809       break;
    810 
    811     case VariableLocation::LOOKUP: {
    812       Comment cmnt(masm_, "[ VariableDeclaration");
    813       DCHECK_EQ(VAR, variable->mode());
    814       DCHECK(!variable->binding_needs_init());
    815       __ li(a2, Operand(variable->name()));
    816       __ Push(a2);
    817       __ CallRuntime(Runtime::kDeclareEvalVar);
    818       PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
    819       break;
    820     }
    821 
    822     case VariableLocation::MODULE:
    823       UNREACHABLE();
    824   }
    825 }
    826 
    827 
    828 void FullCodeGenerator::VisitFunctionDeclaration(
    829     FunctionDeclaration* declaration) {
    830   VariableProxy* proxy = declaration->proxy();
    831   Variable* variable = proxy->var();
    832   switch (variable->location()) {
    833     case VariableLocation::UNALLOCATED: {
    834       FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
    835       DCHECK(!slot.IsInvalid());
    836       globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
    837       Handle<SharedFunctionInfo> function =
    838           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
    839       // Check for stack-overflow exception.
    840       if (function.is_null()) return SetStackOverflow();
    841       globals_->Add(function, zone());
    842       break;
    843     }
    844 
    845     case VariableLocation::PARAMETER:
    846     case VariableLocation::LOCAL: {
    847       Comment cmnt(masm_, "[ FunctionDeclaration");
    848       VisitForAccumulatorValue(declaration->fun());
    849       __ sw(result_register(), StackOperand(variable));
    850       break;
    851     }
    852 
    853     case VariableLocation::CONTEXT: {
    854       Comment cmnt(masm_, "[ FunctionDeclaration");
    855       EmitDebugCheckDeclarationContext(variable);
    856       VisitForAccumulatorValue(declaration->fun());
    857       __ sw(result_register(), ContextMemOperand(cp, variable->index()));
    858       int offset = Context::SlotOffset(variable->index());
    859       // We know that we have written a function, which is not a smi.
    860       __ RecordWriteContextSlot(cp,
    861                                 offset,
    862                                 result_register(),
    863                                 a2,
    864                                 kRAHasBeenSaved,
    865                                 kDontSaveFPRegs,
    866                                 EMIT_REMEMBERED_SET,
    867                                 OMIT_SMI_CHECK);
    868       PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
    869       break;
    870     }
    871 
    872     case VariableLocation::LOOKUP: {
    873       Comment cmnt(masm_, "[ FunctionDeclaration");
    874       __ li(a2, Operand(variable->name()));
    875       PushOperand(a2);
    876       // Push initial value for function declaration.
    877       VisitForStackValue(declaration->fun());
    878       CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
    879       PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
    880       break;
    881     }
    882 
    883     case VariableLocation::MODULE:
    884       UNREACHABLE();
    885   }
    886 }
    887 
    888 
    889 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
    890   // Call the runtime to declare the globals.
    891   __ li(a1, Operand(pairs));
    892   __ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
    893   __ EmitLoadTypeFeedbackVector(a2);
    894   __ Push(a1, a0, a2);
    895   __ CallRuntime(Runtime::kDeclareGlobals);
    896   // Return value is ignored.
    897 }
    898 
    899 
    900 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
    901   Comment cmnt(masm_, "[ SwitchStatement");
    902   Breakable nested_statement(this, stmt);
    903   SetStatementPosition(stmt);
    904 
    905   // Keep the switch value on the stack until a case matches.
    906   VisitForStackValue(stmt->tag());
    907   PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
    908 
    909   ZoneList<CaseClause*>* clauses = stmt->cases();
    910   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
    911 
    912   Label next_test;  // Recycled for each test.
    913   // Compile all the tests with branches to their bodies.
    914   for (int i = 0; i < clauses->length(); i++) {
    915     CaseClause* clause = clauses->at(i);
    916     clause->body_target()->Unuse();
    917 
    918     // The default is not a test, but remember it as final fall through.
    919     if (clause->is_default()) {
    920       default_clause = clause;
    921       continue;
    922     }
    923 
    924     Comment cmnt(masm_, "[ Case comparison");
    925     __ bind(&next_test);
    926     next_test.Unuse();
    927 
    928     // Compile the label expression.
    929     VisitForAccumulatorValue(clause->label());
    930     __ mov(a0, result_register());  // CompareStub requires args in a0, a1.
    931 
    932     // Perform the comparison as if via '==='.
    933     __ lw(a1, MemOperand(sp, 0));  // Switch value.
    934     bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
    935     JumpPatchSite patch_site(masm_);
    936     if (inline_smi_code) {
    937       Label slow_case;
    938       __ or_(a2, a1, a0);
    939       patch_site.EmitJumpIfNotSmi(a2, &slow_case);
    940 
    941       __ Branch(&next_test, ne, a1, Operand(a0));
    942       __ Drop(1);  // Switch value is no longer needed.
    943       __ Branch(clause->body_target());
    944 
    945       __ bind(&slow_case);
    946     }
    947 
    948     // Record position before stub call for type feedback.
    949     SetExpressionPosition(clause);
    950     Handle<Code> ic =
    951         CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
    952     CallIC(ic, clause->CompareId());
    953     patch_site.EmitPatchInfo();
    954 
    955     Label skip;
    956     __ Branch(&skip);
    957     PrepareForBailout(clause, BailoutState::TOS_REGISTER);
    958     __ LoadRoot(at, Heap::kTrueValueRootIndex);
    959     __ Branch(&next_test, ne, v0, Operand(at));
    960     __ Drop(1);
    961     __ Branch(clause->body_target());
    962     __ bind(&skip);
    963 
    964     __ Branch(&next_test, ne, v0, Operand(zero_reg));
    965     __ Drop(1);  // Switch value is no longer needed.
    966     __ Branch(clause->body_target());
    967   }
    968 
    969   // Discard the test value and jump to the default if present, otherwise to
    970   // the end of the statement.
    971   __ bind(&next_test);
    972   DropOperands(1);  // Switch value is no longer needed.
    973   if (default_clause == NULL) {
    974     __ Branch(nested_statement.break_label());
    975   } else {
    976     __ Branch(default_clause->body_target());
    977   }
    978 
    979   // Compile all the case bodies.
    980   for (int i = 0; i < clauses->length(); i++) {
    981     Comment cmnt(masm_, "[ Case body");
    982     CaseClause* clause = clauses->at(i);
    983     __ bind(clause->body_target());
    984     PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
    985     VisitStatements(clause->statements());
    986   }
    987 
    988   __ bind(nested_statement.break_label());
    989   PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
    990 }
    991 
    992 
    993 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
    994   Comment cmnt(masm_, "[ ForInStatement");
    995   SetStatementPosition(stmt, SKIP_BREAK);
    996 
    997   FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
    998 
    999   // Get the object to enumerate over.
   1000   SetExpressionAsStatementPosition(stmt->enumerable());
   1001   VisitForAccumulatorValue(stmt->enumerable());
   1002   __ mov(a0, result_register());
   1003   OperandStackDepthIncrement(5);
   1004 
   1005   Label loop, exit;
   1006   Iteration loop_statement(this, stmt);
   1007   increment_loop_depth();
   1008 
   1009   // If the object is null or undefined, skip over the loop, otherwise convert
   1010   // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
   1011   Label convert, done_convert;
   1012   __ JumpIfSmi(a0, &convert);
   1013   __ GetObjectType(a0, a1, a1);
   1014   __ Branch(USE_DELAY_SLOT, &done_convert, ge, a1,
   1015             Operand(FIRST_JS_RECEIVER_TYPE));
   1016   __ LoadRoot(at, Heap::kNullValueRootIndex);  // In delay slot.
   1017   __ Branch(USE_DELAY_SLOT, &exit, eq, a0, Operand(at));
   1018   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);  // In delay slot.
   1019   __ Branch(&exit, eq, a0, Operand(at));
   1020   __ bind(&convert);
   1021   __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET);
   1022   RestoreContext();
   1023   __ mov(a0, v0);
   1024   __ bind(&done_convert);
   1025   PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   1026   __ push(a0);
   1027 
   1028   // Check cache validity in generated code. If we cannot guarantee cache
   1029   // validity, call the runtime system to check cache validity or get the
   1030   // property names in a fixed array. Note: Proxies never have an enum cache,
   1031   // so will always take the slow path.
   1032   Label call_runtime;
   1033   __ CheckEnumCache(&call_runtime);
   1034 
   1035   // The enum cache is valid.  Load the map of the object being
   1036   // iterated over and use the cache for the iteration.
   1037   Label use_cache;
   1038   __ lw(v0, FieldMemOperand(a0, HeapObject::kMapOffset));
   1039   __ Branch(&use_cache);
   1040 
   1041   // Get the set of properties to enumerate.
   1042   __ bind(&call_runtime);
   1043   __ push(a0);  // Duplicate the enumerable object on the stack.
   1044   __ CallRuntime(Runtime::kForInEnumerate);
   1045   PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
   1046 
   1047   // If we got a map from the runtime call, we can do a fast
   1048   // modification check. Otherwise, we got a fixed array, and we have
   1049   // to do a slow check.
   1050   Label fixed_array;
   1051   __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
   1052   __ LoadRoot(at, Heap::kMetaMapRootIndex);
   1053   __ Branch(&fixed_array, ne, a2, Operand(at));
   1054 
   1055   // We got a map in register v0. Get the enumeration cache from it.
   1056   Label no_descriptors;
   1057   __ bind(&use_cache);
   1058 
   1059   __ EnumLength(a1, v0);
   1060   __ Branch(&no_descriptors, eq, a1, Operand(Smi::kZero));
   1061 
   1062   __ LoadInstanceDescriptors(v0, a2);
   1063   __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheOffset));
   1064   __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheBridgeCacheOffset));
   1065 
   1066   // Set up the four remaining stack slots.
   1067   __ li(a0, Operand(Smi::kZero));
   1068   // Push map, enumeration cache, enumeration cache length (as smi) and zero.
   1069   __ Push(v0, a2, a1, a0);
   1070   __ jmp(&loop);
   1071 
   1072   __ bind(&no_descriptors);
   1073   __ Drop(1);
   1074   __ jmp(&exit);
   1075 
   1076   // We got a fixed array in register v0. Iterate through that.
   1077   __ bind(&fixed_array);
   1078 
   1079   __ li(a1, Operand(Smi::FromInt(1)));  // Smi(1) indicates slow check
   1080   __ Push(a1, v0);  // Smi and array
   1081   __ lw(a1, FieldMemOperand(v0, FixedArray::kLengthOffset));
   1082   __ Push(a1);  // Fixed array length (as smi).
   1083   PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   1084   __ li(a0, Operand(Smi::kZero));
   1085   __ Push(a0);  // Initial index.
   1086 
   1087   // Generate code for doing the condition check.
   1088   __ bind(&loop);
   1089   SetExpressionAsStatementPosition(stmt->each());
   1090 
   1091   // Load the current count to a0, load the length to a1.
   1092   __ lw(a0, MemOperand(sp, 0 * kPointerSize));
   1093   __ lw(a1, MemOperand(sp, 1 * kPointerSize));
   1094   __ Branch(loop_statement.break_label(), hs, a0, Operand(a1));
   1095 
   1096   // Get the current entry of the array into result_register.
   1097   __ lw(a2, MemOperand(sp, 2 * kPointerSize));
   1098   __ Addu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   1099   __ Lsa(t0, a2, a0, kPointerSizeLog2 - kSmiTagSize);
   1100   __ lw(result_register(), MemOperand(t0));  // Current entry.
   1101 
   1102   // Get the expected map from the stack or a smi in the
   1103   // permanent slow case into register a2.
   1104   __ lw(a2, MemOperand(sp, 3 * kPointerSize));
   1105 
   1106   // Check if the expected map still matches that of the enumerable.
   1107   // If not, we may have to filter the key.
   1108   Label update_each;
   1109   __ lw(a1, MemOperand(sp, 4 * kPointerSize));
   1110   __ lw(t0, FieldMemOperand(a1, HeapObject::kMapOffset));
   1111   __ Branch(&update_each, eq, t0, Operand(a2));
   1112 
   1113   // We need to filter the key, record slow-path here.
   1114   int const vector_index = SmiFromSlot(slot)->value();
   1115   __ EmitLoadTypeFeedbackVector(a3);
   1116   __ li(a2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate())));
   1117   __ sw(a2, FieldMemOperand(a3, FixedArray::OffsetOfElementAt(vector_index)));
   1118 
   1119   __ mov(a0, result_register());
   1120   // a0 contains the key. The receiver in a1 is the second argument to the
   1121   // ForInFilter. ForInFilter returns undefined if the receiver doesn't
   1122   // have the key or returns the name-converted key.
   1123   __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET);
   1124   RestoreContext();
   1125   PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   1126   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
   1127   __ Branch(loop_statement.continue_label(), eq, result_register(),
   1128             Operand(at));
   1129 
   1130   // Update the 'each' property or variable from the possibly filtered
   1131   // entry in the result_register.
   1132   __ bind(&update_each);
   1133   // Perform the assignment as if via '='.
   1134   { EffectContext context(this);
   1135     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
   1136     PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   1137   }
   1138 
   1139   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
   1140   PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   1141   // Generate code for the body of the loop.
   1142   Visit(stmt->body());
   1143 
   1144   // Generate code for the going to the next element by incrementing
   1145   // the index (smi) stored on top of the stack.
   1146   __ bind(loop_statement.continue_label());
   1147   PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS);
   1148   __ pop(a0);
   1149   __ Addu(a0, a0, Operand(Smi::FromInt(1)));
   1150   __ push(a0);
   1151 
   1152   EmitBackEdgeBookkeeping(stmt, &loop);
   1153   __ Branch(&loop);
   1154 
   1155   // Remove the pointers stored on the stack.
   1156   __ bind(loop_statement.break_label());
   1157   DropOperands(5);
   1158 
   1159   // Exit and decrement the loop depth.
   1160   PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   1161   __ bind(&exit);
   1162   decrement_loop_depth();
   1163 }
   1164 
   1165 
   1166 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
   1167                                           FeedbackVectorSlot slot) {
   1168   DCHECK(NeedsHomeObject(initializer));
   1169   __ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
   1170   __ lw(StoreDescriptor::ValueRegister(),
   1171         MemOperand(sp, offset * kPointerSize));
   1172   CallStoreIC(slot, isolate()->factory()->home_object_symbol());
   1173 }
   1174 
   1175 
   1176 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
   1177                                                      int offset,
   1178                                                      FeedbackVectorSlot slot) {
   1179   DCHECK(NeedsHomeObject(initializer));
   1180   __ Move(StoreDescriptor::ReceiverRegister(), v0);
   1181   __ lw(StoreDescriptor::ValueRegister(),
   1182         MemOperand(sp, offset * kPointerSize));
   1183   CallStoreIC(slot, isolate()->factory()->home_object_symbol());
   1184 }
   1185 
   1186 
   1187 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
   1188                                                       TypeofMode typeof_mode,
   1189                                                       Label* slow) {
   1190   Register current = cp;
   1191   Register next = a1;
   1192   Register temp = a2;
   1193 
   1194   int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
   1195   for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
   1196     if (!s->NeedsContext()) continue;
   1197     if (s->calls_sloppy_eval()) {
   1198       // Check that extension is "the hole".
   1199       __ lw(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
   1200       __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
   1201     }
   1202     // Load next context in chain.
   1203     __ lw(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
   1204     // Walk the rest of the chain without clobbering cp.
   1205     current = next;
   1206     to_check--;
   1207   }
   1208 
   1209   // All extension objects were empty and it is safe to use a normal global
   1210   // load machinery.
   1211   EmitGlobalVariableLoad(proxy, typeof_mode);
   1212 }
   1213 
   1214 
   1215 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
   1216                                                                 Label* slow) {
   1217   DCHECK(var->IsContextSlot());
   1218   Register context = cp;
   1219   Register next = a3;
   1220   Register temp = t0;
   1221 
   1222   for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
   1223     if (s->NeedsContext()) {
   1224       if (s->calls_sloppy_eval()) {
   1225         // Check that extension is "the hole".
   1226         __ lw(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
   1227         __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
   1228       }
   1229       __ lw(next, ContextMemOperand(context, Context::PREVIOUS_INDEX));
   1230       // Walk the rest of the chain without clobbering cp.
   1231       context = next;
   1232     }
   1233   }
   1234   // Check that last extension is "the hole".
   1235   __ lw(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
   1236   __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
   1237 
   1238   // This function is used only for loads, not stores, so it's safe to
   1239   // return an cp-based operand (the write barrier cannot be allowed to
   1240   // destroy the cp register).
   1241   return ContextMemOperand(context, var->index());
   1242 }
   1243 
   1244 
   1245 void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
   1246                                                   TypeofMode typeof_mode,
   1247                                                   Label* slow, Label* done) {
   1248   // Generate fast-case code for variables that might be shadowed by
   1249   // eval-introduced variables.  Eval is used a lot without
   1250   // introducing variables.  In those cases, we do not want to
   1251   // perform a runtime call for all variables in the scope
   1252   // containing the eval.
   1253   Variable* var = proxy->var();
   1254   if (var->mode() == DYNAMIC_GLOBAL) {
   1255     EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
   1256     __ Branch(done);
   1257   } else if (var->mode() == DYNAMIC_LOCAL) {
   1258     Variable* local = var->local_if_not_shadowed();
   1259     __ lw(v0, ContextSlotOperandCheckExtensions(local, slow));
   1260     if (local->binding_needs_init()) {
   1261       __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
   1262       __ subu(at, v0, at);  // Sub as compare: at == 0 on eq.
   1263       __ Branch(done, ne, at, Operand(zero_reg));
   1264       __ li(a0, Operand(var->name()));
   1265       __ push(a0);
   1266       __ CallRuntime(Runtime::kThrowReferenceError);
   1267     } else {
   1268       __ Branch(done);
   1269     }
   1270   }
   1271 }
   1272 
   1273 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
   1274                                          TypeofMode typeof_mode) {
   1275   // Record position before possible IC call.
   1276   SetExpressionPosition(proxy);
   1277   PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   1278   Variable* var = proxy->var();
   1279 
   1280   // Three cases: global variables, lookup variables, and all other types of
   1281   // variables.
   1282   switch (var->location()) {
   1283     case VariableLocation::UNALLOCATED: {
   1284       Comment cmnt(masm_, "[ Global variable");
   1285       EmitGlobalVariableLoad(proxy, typeof_mode);
   1286       context()->Plug(v0);
   1287       break;
   1288     }
   1289 
   1290     case VariableLocation::PARAMETER:
   1291     case VariableLocation::LOCAL:
   1292     case VariableLocation::CONTEXT: {
   1293       DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
   1294       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
   1295                                                : "[ Stack variable");
   1296       if (proxy->hole_check_mode() == HoleCheckMode::kRequired) {
   1297         // Throw a reference error when using an uninitialized let/const
   1298         // binding in harmony mode.
   1299         Label done;
   1300         GetVar(v0, var);
   1301         __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
   1302         __ subu(at, v0, at);  // Sub as compare: at == 0 on eq.
   1303         __ Branch(&done, ne, at, Operand(zero_reg));
   1304         __ li(a0, Operand(var->name()));
   1305         __ push(a0);
   1306         __ CallRuntime(Runtime::kThrowReferenceError);
   1307         __ bind(&done);
   1308         context()->Plug(v0);
   1309         break;
   1310       }
   1311       context()->Plug(var);
   1312       break;
   1313     }
   1314 
   1315     case VariableLocation::LOOKUP: {
   1316       Comment cmnt(masm_, "[ Lookup variable");
   1317       Label done, slow;
   1318       // Generate code for loading from variables potentially shadowed
   1319       // by eval-introduced variables.
   1320       EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done);
   1321       __ bind(&slow);
   1322       __ Push(var->name());
   1323       Runtime::FunctionId function_id =
   1324           typeof_mode == NOT_INSIDE_TYPEOF
   1325               ? Runtime::kLoadLookupSlot
   1326               : Runtime::kLoadLookupSlotInsideTypeof;
   1327       __ CallRuntime(function_id);
   1328       __ bind(&done);
   1329       context()->Plug(v0);
   1330       break;
   1331     }
   1332 
   1333     case VariableLocation::MODULE:
   1334       UNREACHABLE();
   1335   }
   1336 }
   1337 
   1338 
   1339 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   1340   Expression* expression = (property == NULL) ? NULL : property->value();
   1341   if (expression == NULL) {
   1342     __ LoadRoot(a1, Heap::kNullValueRootIndex);
   1343     PushOperand(a1);
   1344   } else {
   1345     VisitForStackValue(expression);
   1346     if (NeedsHomeObject(expression)) {
   1347       DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
   1348              property->kind() == ObjectLiteral::Property::SETTER);
   1349       int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
   1350       EmitSetHomeObject(expression, offset, property->GetSlot());
   1351     }
   1352   }
   1353 }
   1354 
   1355 
   1356 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   1357   Comment cmnt(masm_, "[ ObjectLiteral");
   1358 
   1359   Handle<FixedArray> constant_properties = expr->constant_properties();
   1360   __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   1361   __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
   1362   __ li(a1, Operand(constant_properties));
   1363   __ li(a0, Operand(Smi::FromInt(expr->ComputeFlags())));
   1364   if (MustCreateObjectLiteralWithRuntime(expr)) {
   1365     __ Push(a3, a2, a1, a0);
   1366     __ CallRuntime(Runtime::kCreateObjectLiteral);
   1367   } else {
   1368     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
   1369     __ CallStub(&stub);
   1370     RestoreContext();
   1371   }
   1372   PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
   1373 
   1374   // If result_saved is true the result is on top of the stack.  If
   1375   // result_saved is false the result is in v0.
   1376   bool result_saved = false;
   1377 
   1378   AccessorTable accessor_table(zone());
   1379   int property_index = 0;
   1380   for (; property_index < expr->properties()->length(); property_index++) {
   1381     ObjectLiteral::Property* property = expr->properties()->at(property_index);
   1382     if (property->is_computed_name()) break;
   1383     if (property->IsCompileTimeValue()) continue;
   1384 
   1385     Literal* key = property->key()->AsLiteral();
   1386     Expression* value = property->value();
   1387     if (!result_saved) {
   1388       PushOperand(v0);  // Save result on stack.
   1389       result_saved = true;
   1390     }
   1391     switch (property->kind()) {
   1392       case ObjectLiteral::Property::CONSTANT:
   1393         UNREACHABLE();
   1394       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   1395         DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
   1396         // Fall through.
   1397       case ObjectLiteral::Property::COMPUTED:
   1398         // It is safe to use [[Put]] here because the boilerplate already
   1399         // contains computed properties with an uninitialized value.
   1400         if (key->IsStringLiteral()) {
   1401           DCHECK(key->IsPropertyName());
   1402           if (property->emit_store()) {
   1403             VisitForAccumulatorValue(value);
   1404             __ mov(StoreDescriptor::ValueRegister(), result_register());
   1405             DCHECK(StoreDescriptor::ValueRegister().is(a0));
   1406             __ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
   1407             CallStoreIC(property->GetSlot(0), key->value());
   1408             PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
   1409 
   1410             if (NeedsHomeObject(value)) {
   1411               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
   1412             }
   1413           } else {
   1414             VisitForEffect(value);
   1415           }
   1416           break;
   1417         }
   1418         // Duplicate receiver on stack.
   1419         __ lw(a0, MemOperand(sp));
   1420         PushOperand(a0);
   1421         VisitForStackValue(key);
   1422         VisitForStackValue(value);
   1423         if (property->emit_store()) {
   1424           if (NeedsHomeObject(value)) {
   1425             EmitSetHomeObject(value, 2, property->GetSlot());
   1426           }
   1427           __ li(a0, Operand(Smi::FromInt(SLOPPY)));  // PropertyAttributes.
   1428           PushOperand(a0);
   1429           CallRuntimeWithOperands(Runtime::kSetProperty);
   1430         } else {
   1431           DropOperands(3);
   1432         }
   1433         break;
   1434       case ObjectLiteral::Property::PROTOTYPE:
   1435         // Duplicate receiver on stack.
   1436         __ lw(a0, MemOperand(sp));
   1437         PushOperand(a0);
   1438         VisitForStackValue(value);
   1439         DCHECK(property->emit_store());
   1440         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
   1441         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
   1442                                BailoutState::NO_REGISTERS);
   1443         break;
   1444       case ObjectLiteral::Property::GETTER:
   1445         if (property->emit_store()) {
   1446           AccessorTable::Iterator it = accessor_table.lookup(key);
   1447           it->second->bailout_id = expr->GetIdForPropertySet(property_index);
   1448           it->second->getter = property;
   1449         }
   1450         break;
   1451       case ObjectLiteral::Property::SETTER:
   1452         if (property->emit_store()) {
   1453           AccessorTable::Iterator it = accessor_table.lookup(key);
   1454           it->second->bailout_id = expr->GetIdForPropertySet(property_index);
   1455           it->second->setter = property;
   1456         }
   1457         break;
   1458     }
   1459   }
   1460 
   1461   // Emit code to define accessors, using only a single call to the runtime for
   1462   // each pair of corresponding getters and setters.
   1463   for (AccessorTable::Iterator it = accessor_table.begin();
   1464        it != accessor_table.end();
   1465        ++it) {
   1466     __ lw(a0, MemOperand(sp));  // Duplicate receiver.
   1467     PushOperand(a0);
   1468     VisitForStackValue(it->first);
   1469     EmitAccessor(it->second->getter);
   1470     EmitAccessor(it->second->setter);
   1471     __ li(a0, Operand(Smi::FromInt(NONE)));
   1472     PushOperand(a0);
   1473     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
   1474     PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   1475   }
   1476 
   1477   // Object literals have two parts. The "static" part on the left contains no
   1478   // computed property names, and so we can compute its map ahead of time; see
   1479   // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part
   1480   // starts with the first computed property name, and continues with all
   1481   // properties to its right.  All the code from above initializes the static
   1482   // component of the object literal, and arranges for the map of the result to
   1483   // reflect the static order in which the keys appear. For the dynamic
   1484   // properties, we compile them into a series of "SetOwnProperty" runtime
   1485   // calls. This will preserve insertion order.
   1486   for (; property_index < expr->properties()->length(); property_index++) {
   1487     ObjectLiteral::Property* property = expr->properties()->at(property_index);
   1488 
   1489     Expression* value = property->value();
   1490     if (!result_saved) {
   1491       PushOperand(v0);  // Save result on the stack
   1492       result_saved = true;
   1493     }
   1494 
   1495     __ lw(a0, MemOperand(sp));  // Duplicate receiver.
   1496     PushOperand(a0);
   1497 
   1498     if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
   1499       DCHECK(!property->is_computed_name());
   1500       VisitForStackValue(value);
   1501       DCHECK(property->emit_store());
   1502       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
   1503       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
   1504                              BailoutState::NO_REGISTERS);
   1505     } else {
   1506       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
   1507       VisitForStackValue(value);
   1508       if (NeedsHomeObject(value)) {
   1509         EmitSetHomeObject(value, 2, property->GetSlot());
   1510       }
   1511 
   1512       switch (property->kind()) {
   1513         case ObjectLiteral::Property::CONSTANT:
   1514         case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   1515         case ObjectLiteral::Property::COMPUTED:
   1516           if (property->emit_store()) {
   1517             PushOperand(Smi::FromInt(NONE));
   1518             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
   1519             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
   1520             PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
   1521                                    BailoutState::NO_REGISTERS);
   1522           } else {
   1523             DropOperands(3);
   1524           }
   1525           break;
   1526 
   1527         case ObjectLiteral::Property::PROTOTYPE:
   1528           UNREACHABLE();
   1529           break;
   1530 
   1531         case ObjectLiteral::Property::GETTER:
   1532           PushOperand(Smi::FromInt(NONE));
   1533           CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
   1534           break;
   1535 
   1536         case ObjectLiteral::Property::SETTER:
   1537           PushOperand(Smi::FromInt(NONE));
   1538           CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
   1539           break;
   1540       }
   1541     }
   1542   }
   1543 
   1544   if (result_saved) {
   1545     context()->PlugTOS();
   1546   } else {
   1547     context()->Plug(v0);
   1548   }
   1549 }
   1550 
   1551 
   1552 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
   1553   Comment cmnt(masm_, "[ ArrayLiteral");
   1554 
   1555   Handle<FixedArray> constant_elements = expr->constant_elements();
   1556   bool has_fast_elements =
   1557       IsFastObjectElementsKind(expr->constant_elements_kind());
   1558 
   1559   AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
   1560   if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
   1561     // If the only customer of allocation sites is transitioning, then
   1562     // we can turn it off if we don't have anywhere else to transition to.
   1563     allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
   1564   }
   1565 
   1566   __ mov(a0, result_register());
   1567   __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   1568   __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
   1569   __ li(a1, Operand(constant_elements));
   1570   if (MustCreateArrayLiteralWithRuntime(expr)) {
   1571     __ li(a0, Operand(Smi::FromInt(expr->ComputeFlags())));
   1572     __ Push(a3, a2, a1, a0);
   1573     __ CallRuntime(Runtime::kCreateArrayLiteral);
   1574   } else {
   1575     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
   1576     __ CallStub(&stub);
   1577     RestoreContext();
   1578   }
   1579   PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
   1580 
   1581   bool result_saved = false;  // Is the result saved to the stack?
   1582   ZoneList<Expression*>* subexprs = expr->values();
   1583   int length = subexprs->length();
   1584 
   1585   // Emit code to evaluate all the non-constant subexpressions and to store
   1586   // them into the newly cloned array.
   1587   for (int array_index = 0; array_index < length; array_index++) {
   1588     Expression* subexpr = subexprs->at(array_index);
   1589     DCHECK(!subexpr->IsSpread());
   1590 
   1591     // If the subexpression is a literal or a simple materialized literal it
   1592     // is already set in the cloned array.
   1593     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
   1594 
   1595     if (!result_saved) {
   1596       PushOperand(v0);  // array literal
   1597       result_saved = true;
   1598     }
   1599 
   1600     VisitForAccumulatorValue(subexpr);
   1601 
   1602     __ li(StoreDescriptor::NameRegister(), Operand(Smi::FromInt(array_index)));
   1603     __ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   1604     __ mov(StoreDescriptor::ValueRegister(), result_register());
   1605     CallKeyedStoreIC(expr->LiteralFeedbackSlot());
   1606 
   1607     PrepareForBailoutForId(expr->GetIdForElement(array_index),
   1608                            BailoutState::NO_REGISTERS);
   1609   }
   1610 
   1611   if (result_saved) {
   1612     context()->PlugTOS();
   1613   } else {
   1614     context()->Plug(v0);
   1615   }
   1616 }
   1617 
   1618 
   1619 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
   1620   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
   1621 
   1622   Comment cmnt(masm_, "[ Assignment");
   1623 
   1624   Property* property = expr->target()->AsProperty();
   1625   LhsKind assign_type = Property::GetAssignType(property);
   1626 
   1627   // Evaluate LHS expression.
   1628   switch (assign_type) {
   1629     case VARIABLE:
   1630       // Nothing to do here.
   1631       break;
   1632     case NAMED_PROPERTY:
   1633       if (expr->is_compound()) {
   1634         // We need the receiver both on the stack and in the register.
   1635         VisitForStackValue(property->obj());
   1636         __ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   1637       } else {
   1638         VisitForStackValue(property->obj());
   1639       }
   1640       break;
   1641     case NAMED_SUPER_PROPERTY:
   1642       VisitForStackValue(
   1643           property->obj()->AsSuperPropertyReference()->this_var());
   1644       VisitForAccumulatorValue(
   1645           property->obj()->AsSuperPropertyReference()->home_object());
   1646       PushOperand(result_register());
   1647       if (expr->is_compound()) {
   1648         const Register scratch = a1;
   1649         __ lw(scratch, MemOperand(sp, kPointerSize));
   1650         PushOperands(scratch, result_register());
   1651       }
   1652       break;
   1653     case KEYED_SUPER_PROPERTY: {
   1654       VisitForStackValue(
   1655           property->obj()->AsSuperPropertyReference()->this_var());
   1656       VisitForStackValue(
   1657           property->obj()->AsSuperPropertyReference()->home_object());
   1658       VisitForAccumulatorValue(property->key());
   1659       PushOperand(result_register());
   1660       if (expr->is_compound()) {
   1661         const Register scratch1 = t0;
   1662         const Register scratch2 = a1;
   1663         __ lw(scratch1, MemOperand(sp, 2 * kPointerSize));
   1664         __ lw(scratch2, MemOperand(sp, 1 * kPointerSize));
   1665         PushOperands(scratch1, scratch2, result_register());
   1666       }
   1667       break;
   1668     }
   1669     case KEYED_PROPERTY:
   1670       // We need the key and receiver on both the stack and in v0 and a1.
   1671       if (expr->is_compound()) {
   1672         VisitForStackValue(property->obj());
   1673         VisitForStackValue(property->key());
   1674         __ lw(LoadDescriptor::ReceiverRegister(),
   1675               MemOperand(sp, 1 * kPointerSize));
   1676         __ lw(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
   1677       } else {
   1678         VisitForStackValue(property->obj());
   1679         VisitForStackValue(property->key());
   1680       }
   1681       break;
   1682   }
   1683 
   1684   // For compound assignments we need another deoptimization point after the
   1685   // variable/property load.
   1686   if (expr->is_compound()) {
   1687     { AccumulatorValueContext context(this);
   1688       switch (assign_type) {
   1689         case VARIABLE:
   1690           EmitVariableLoad(expr->target()->AsVariableProxy());
   1691           PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
   1692           break;
   1693         case NAMED_PROPERTY:
   1694           EmitNamedPropertyLoad(property);
   1695           PrepareForBailoutForId(property->LoadId(),
   1696                                  BailoutState::TOS_REGISTER);
   1697           break;
   1698         case NAMED_SUPER_PROPERTY:
   1699           EmitNamedSuperPropertyLoad(property);
   1700           PrepareForBailoutForId(property->LoadId(),
   1701                                  BailoutState::TOS_REGISTER);
   1702           break;
   1703         case KEYED_SUPER_PROPERTY:
   1704           EmitKeyedSuperPropertyLoad(property);
   1705           PrepareForBailoutForId(property->LoadId(),
   1706                                  BailoutState::TOS_REGISTER);
   1707           break;
   1708         case KEYED_PROPERTY:
   1709           EmitKeyedPropertyLoad(property);
   1710           PrepareForBailoutForId(property->LoadId(),
   1711                                  BailoutState::TOS_REGISTER);
   1712           break;
   1713       }
   1714     }
   1715 
   1716     Token::Value op = expr->binary_op();
   1717     PushOperand(v0);  // Left operand goes on the stack.
   1718     VisitForAccumulatorValue(expr->value());
   1719 
   1720     AccumulatorValueContext context(this);
   1721     if (ShouldInlineSmiCase(op)) {
   1722       EmitInlineSmiBinaryOp(expr->binary_operation(),
   1723                             op,
   1724                             expr->target(),
   1725                             expr->value());
   1726     } else {
   1727       EmitBinaryOp(expr->binary_operation(), op);
   1728     }
   1729 
   1730     // Deoptimization point in case the binary operation may have side effects.
   1731     PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   1732   } else {
   1733     VisitForAccumulatorValue(expr->value());
   1734   }
   1735 
   1736   SetExpressionPosition(expr);
   1737 
   1738   // Store the value.
   1739   switch (assign_type) {
   1740     case VARIABLE: {
   1741       VariableProxy* proxy = expr->target()->AsVariableProxy();
   1742       EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(),
   1743                              proxy->hole_check_mode());
   1744       PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   1745       context()->Plug(v0);
   1746       break;
   1747     }
   1748     case NAMED_PROPERTY:
   1749       EmitNamedPropertyAssignment(expr);
   1750       break;
   1751     case NAMED_SUPER_PROPERTY:
   1752       EmitNamedSuperPropertyStore(property);
   1753       context()->Plug(v0);
   1754       break;
   1755     case KEYED_SUPER_PROPERTY:
   1756       EmitKeyedSuperPropertyStore(property);
   1757       context()->Plug(v0);
   1758       break;
   1759     case KEYED_PROPERTY:
   1760       EmitKeyedPropertyAssignment(expr);
   1761       break;
   1762   }
   1763 }
   1764 
   1765 
   1766 void FullCodeGenerator::VisitYield(Yield* expr) {
   1767   Comment cmnt(masm_, "[ Yield");
   1768   SetExpressionPosition(expr);
   1769 
   1770   // Evaluate yielded value first; the initial iterator definition depends on
   1771   // this.  It stays on the stack while we update the iterator.
   1772   VisitForStackValue(expr->expression());
   1773 
   1774   Label suspend, continuation, post_runtime, resume, exception;
   1775 
   1776   __ jmp(&suspend);
   1777   __ bind(&continuation);
   1778   // When we arrive here, v0 holds the generator object.
   1779   __ RecordGeneratorContinuation();
   1780   __ lw(a1, FieldMemOperand(v0, JSGeneratorObject::kResumeModeOffset));
   1781   __ lw(v0, FieldMemOperand(v0, JSGeneratorObject::kInputOrDebugPosOffset));
   1782   __ Branch(&resume, eq, a1, Operand(Smi::FromInt(JSGeneratorObject::kNext)));
   1783   __ Push(result_register());
   1784   __ Branch(&exception, eq, a1,
   1785             Operand(Smi::FromInt(JSGeneratorObject::kThrow)));
   1786   EmitCreateIteratorResult(true);
   1787   EmitUnwindAndReturn();
   1788 
   1789   __ bind(&exception);
   1790   __ CallRuntime(expr->rethrow_on_exception() ? Runtime::kReThrow
   1791                                               : Runtime::kThrow);
   1792 
   1793   __ bind(&suspend);
   1794   OperandStackDepthIncrement(1);  // Not popped on this path.
   1795   VisitForAccumulatorValue(expr->generator_object());
   1796   DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
   1797   __ li(a1, Operand(Smi::FromInt(continuation.pos())));
   1798   __ sw(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset));
   1799   __ sw(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset));
   1800   __ mov(a1, cp);
   1801   __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2,
   1802                       kRAHasBeenSaved, kDontSaveFPRegs);
   1803   __ Addu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset));
   1804   __ Branch(&post_runtime, eq, sp, Operand(a1));
   1805   __ push(v0);  // generator object
   1806   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
   1807   RestoreContext();
   1808   __ bind(&post_runtime);
   1809   PopOperand(result_register());
   1810   EmitReturnSequence();
   1811 
   1812   __ bind(&resume);
   1813   context()->Plug(result_register());
   1814 }
   1815 
   1816 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
   1817   OperandStackDepthIncrement(2);
   1818   __ Push(reg1, reg2);
   1819 }
   1820 
   1821 void FullCodeGenerator::PushOperands(Register reg1, Register reg2,
   1822                                      Register reg3) {
   1823   OperandStackDepthIncrement(3);
   1824   __ Push(reg1, reg2, reg3);
   1825 }
   1826 
   1827 void FullCodeGenerator::PushOperands(Register reg1, Register reg2,
   1828                                      Register reg3, Register reg4) {
   1829   OperandStackDepthIncrement(4);
   1830   __ Push(reg1, reg2, reg3, reg4);
   1831 }
   1832 
   1833 void FullCodeGenerator::PopOperands(Register reg1, Register reg2) {
   1834   OperandStackDepthDecrement(2);
   1835   __ Pop(reg1, reg2);
   1836 }
   1837 
   1838 void FullCodeGenerator::EmitOperandStackDepthCheck() {
   1839   if (FLAG_debug_code) {
   1840     int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
   1841                         operand_stack_depth_ * kPointerSize;
   1842     __ Subu(v0, fp, sp);
   1843     __ Assert(eq, kUnexpectedStackDepth, v0, Operand(expected_diff));
   1844   }
   1845 }
   1846 
   1847 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   1848   Label allocate, done_allocate;
   1849 
   1850   __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate,
   1851               NO_ALLOCATION_FLAGS);
   1852   __ jmp(&done_allocate);
   1853 
   1854   __ bind(&allocate);
   1855   __ Push(Smi::FromInt(JSIteratorResult::kSize));
   1856   __ CallRuntime(Runtime::kAllocateInNewSpace);
   1857 
   1858   __ bind(&done_allocate);
   1859   __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, a1);
   1860   PopOperand(a2);
   1861   __ LoadRoot(a3,
   1862               done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
   1863   __ LoadRoot(t0, Heap::kEmptyFixedArrayRootIndex);
   1864   __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
   1865   __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset));
   1866   __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
   1867   __ sw(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset));
   1868   __ sw(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset));
   1869   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
   1870 }
   1871 
   1872 
   1873 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
   1874                                               Token::Value op,
   1875                                               Expression* left_expr,
   1876                                               Expression* right_expr) {
   1877   Label done, smi_case, stub_call;
   1878 
   1879   Register scratch1 = a2;
   1880   Register scratch2 = a3;
   1881 
   1882   // Get the arguments.
   1883   Register left = a1;
   1884   Register right = a0;
   1885   PopOperand(left);
   1886   __ mov(a0, result_register());
   1887 
   1888   // Perform combined smi check on both operands.
   1889   __ Or(scratch1, left, Operand(right));
   1890   STATIC_ASSERT(kSmiTag == 0);
   1891   JumpPatchSite patch_site(masm_);
   1892   patch_site.EmitJumpIfSmi(scratch1, &smi_case);
   1893 
   1894   __ bind(&stub_call);
   1895   Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
   1896   CallIC(code, expr->BinaryOperationFeedbackId());
   1897   patch_site.EmitPatchInfo();
   1898   __ jmp(&done);
   1899 
   1900   __ bind(&smi_case);
   1901   // Smi case. This code works the same way as the smi-smi case in the type
   1902   // recording binary operation stub, see
   1903   switch (op) {
   1904     case Token::SAR:
   1905       __ GetLeastBitsFromSmi(scratch1, right, 5);
   1906       __ srav(right, left, scratch1);
   1907       __ And(v0, right, Operand(~kSmiTagMask));
   1908       break;
   1909     case Token::SHL: {
   1910       __ SmiUntag(scratch1, left);
   1911       __ GetLeastBitsFromSmi(scratch2, right, 5);
   1912       __ sllv(scratch1, scratch1, scratch2);
   1913       __ Addu(scratch2, scratch1, Operand(0x40000000));
   1914       __ Branch(&stub_call, lt, scratch2, Operand(zero_reg));
   1915       __ SmiTag(v0, scratch1);
   1916       break;
   1917     }
   1918     case Token::SHR: {
   1919       __ SmiUntag(scratch1, left);
   1920       __ GetLeastBitsFromSmi(scratch2, right, 5);
   1921       __ srlv(scratch1, scratch1, scratch2);
   1922       __ And(scratch2, scratch1, 0xc0000000);
   1923       __ Branch(&stub_call, ne, scratch2, Operand(zero_reg));
   1924       __ SmiTag(v0, scratch1);
   1925       break;
   1926     }
   1927     case Token::ADD:
   1928       __ AddBranchOvf(v0, left, Operand(right), &stub_call);
   1929       break;
   1930     case Token::SUB:
   1931       __ SubBranchOvf(v0, left, Operand(right), &stub_call);
   1932       break;
   1933     case Token::MUL: {
   1934       __ SmiUntag(scratch1, right);
   1935       __ Mul(scratch2, v0, left, scratch1);
   1936       __ sra(scratch1, v0, 31);
   1937       __ Branch(&stub_call, ne, scratch1, Operand(scratch2));
   1938       __ Branch(&done, ne, v0, Operand(zero_reg));
   1939       __ Addu(scratch2, right, left);
   1940       __ Branch(&stub_call, lt, scratch2, Operand(zero_reg));
   1941       DCHECK(Smi::kZero == 0);
   1942       __ mov(v0, zero_reg);
   1943       break;
   1944     }
   1945     case Token::BIT_OR:
   1946       __ Or(v0, left, Operand(right));
   1947       break;
   1948     case Token::BIT_AND:
   1949       __ And(v0, left, Operand(right));
   1950       break;
   1951     case Token::BIT_XOR:
   1952       __ Xor(v0, left, Operand(right));
   1953       break;
   1954     default:
   1955       UNREACHABLE();
   1956   }
   1957 
   1958   __ bind(&done);
   1959   context()->Plug(v0);
   1960 }
   1961 
   1962 
   1963 void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
   1964   for (int i = 0; i < lit->properties()->length(); i++) {
   1965     ClassLiteral::Property* property = lit->properties()->at(i);
   1966     Expression* value = property->value();
   1967 
   1968     Register scratch = a1;
   1969     if (property->is_static()) {
   1970       __ lw(scratch, MemOperand(sp, kPointerSize));  // constructor
   1971     } else {
   1972       __ lw(scratch, MemOperand(sp, 0));  // prototype
   1973     }
   1974     PushOperand(scratch);
   1975     EmitPropertyKey(property, lit->GetIdForProperty(i));
   1976 
   1977     // The static prototype property is read only. We handle the non computed
   1978     // property name case in the parser. Since this is the only case where we
   1979     // need to check for an own read only property we special case this so we do
   1980     // not need to do this for every property.
   1981     if (property->is_static() && property->is_computed_name()) {
   1982       __ CallRuntime(Runtime::kThrowIfStaticPrototype);
   1983       __ push(v0);
   1984     }
   1985 
   1986     VisitForStackValue(value);
   1987     if (NeedsHomeObject(value)) {
   1988       EmitSetHomeObject(value, 2, property->GetSlot());
   1989     }
   1990 
   1991     switch (property->kind()) {
   1992       case ClassLiteral::Property::METHOD:
   1993         PushOperand(Smi::FromInt(DONT_ENUM));
   1994         PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
   1995         CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
   1996         break;
   1997 
   1998       case ClassLiteral::Property::GETTER:
   1999         PushOperand(Smi::FromInt(DONT_ENUM));
   2000         CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
   2001         break;
   2002 
   2003       case ClassLiteral::Property::SETTER:
   2004         PushOperand(Smi::FromInt(DONT_ENUM));
   2005         CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
   2006         break;
   2007 
   2008       case ClassLiteral::Property::FIELD:
   2009       default:
   2010         UNREACHABLE();
   2011     }
   2012   }
   2013 }
   2014 
   2015 
   2016 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
   2017   __ mov(a0, result_register());
   2018   PopOperand(a1);
   2019   Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
   2020   JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
   2021   CallIC(code, expr->BinaryOperationFeedbackId());
   2022   patch_site.EmitPatchInfo();
   2023   context()->Plug(v0);
   2024 }
   2025 
   2026 
   2027 void FullCodeGenerator::EmitAssignment(Expression* expr,
   2028                                        FeedbackVectorSlot slot) {
   2029   DCHECK(expr->IsValidReferenceExpressionOrThis());
   2030 
   2031   Property* prop = expr->AsProperty();
   2032   LhsKind assign_type = Property::GetAssignType(prop);
   2033 
   2034   switch (assign_type) {
   2035     case VARIABLE: {
   2036       VariableProxy* proxy = expr->AsVariableProxy();
   2037       EffectContext context(this);
   2038       EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot,
   2039                              proxy->hole_check_mode());
   2040       break;
   2041     }
   2042     case NAMED_PROPERTY: {
   2043       PushOperand(result_register());  // Preserve value.
   2044       VisitForAccumulatorValue(prop->obj());
   2045       __ mov(StoreDescriptor::ReceiverRegister(), result_register());
   2046       PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
   2047       CallStoreIC(slot, prop->key()->AsLiteral()->value());
   2048       break;
   2049     }
   2050     case NAMED_SUPER_PROPERTY: {
   2051       PushOperand(v0);
   2052       VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
   2053       VisitForAccumulatorValue(
   2054           prop->obj()->AsSuperPropertyReference()->home_object());
   2055       // stack: value, this; v0: home_object
   2056       Register scratch = a2;
   2057       Register scratch2 = a3;
   2058       __ mov(scratch, result_register());             // home_object
   2059       __ lw(v0, MemOperand(sp, kPointerSize));        // value
   2060       __ lw(scratch2, MemOperand(sp, 0));             // this
   2061       __ sw(scratch2, MemOperand(sp, kPointerSize));  // this
   2062       __ sw(scratch, MemOperand(sp, 0));              // home_object
   2063       // stack: this, home_object; v0: value
   2064       EmitNamedSuperPropertyStore(prop);
   2065       break;
   2066     }
   2067     case KEYED_SUPER_PROPERTY: {
   2068       PushOperand(v0);
   2069       VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
   2070       VisitForStackValue(
   2071           prop->obj()->AsSuperPropertyReference()->home_object());
   2072       VisitForAccumulatorValue(prop->key());
   2073       Register scratch = a2;
   2074       Register scratch2 = a3;
   2075       __ lw(scratch2, MemOperand(sp, 2 * kPointerSize));  // value
   2076       // stack: value, this, home_object; v0: key, a3: value
   2077       __ lw(scratch, MemOperand(sp, kPointerSize));  // this
   2078       __ sw(scratch, MemOperand(sp, 2 * kPointerSize));
   2079       __ lw(scratch, MemOperand(sp, 0));  // home_object
   2080       __ sw(scratch, MemOperand(sp, kPointerSize));
   2081       __ sw(v0, MemOperand(sp, 0));
   2082       __ Move(v0, scratch2);
   2083       // stack: this, home_object, key; v0: value.
   2084       EmitKeyedSuperPropertyStore(prop);
   2085       break;
   2086     }
   2087     case KEYED_PROPERTY: {
   2088       PushOperand(result_register());  // Preserve value.
   2089       VisitForStackValue(prop->obj());
   2090       VisitForAccumulatorValue(prop->key());
   2091       __ mov(StoreDescriptor::NameRegister(), result_register());
   2092       PopOperands(StoreDescriptor::ValueRegister(),
   2093                   StoreDescriptor::ReceiverRegister());
   2094       CallKeyedStoreIC(slot);
   2095       break;
   2096     }
   2097   }
   2098   context()->Plug(v0);
   2099 }
   2100 
   2101 
   2102 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
   2103     Variable* var, MemOperand location) {
   2104   __ sw(result_register(), location);
   2105   if (var->IsContextSlot()) {
   2106     // RecordWrite may destroy all its register arguments.
   2107     __ Move(a3, result_register());
   2108     int offset = Context::SlotOffset(var->index());
   2109     __ RecordWriteContextSlot(
   2110         a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs);
   2111   }
   2112 }
   2113 
   2114 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
   2115                                                FeedbackVectorSlot slot,
   2116                                                HoleCheckMode hole_check_mode) {
   2117   if (var->IsUnallocated()) {
   2118     // Global var, const, or let.
   2119     __ mov(StoreDescriptor::ValueRegister(), result_register());
   2120     __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
   2121     CallStoreIC(slot, var->name());
   2122 
   2123   } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
   2124     DCHECK(!var->IsLookupSlot());
   2125     DCHECK(var->IsStackAllocated() || var->IsContextSlot());
   2126     MemOperand location = VarOperand(var, a1);
   2127     // Perform an initialization check for lexically declared variables.
   2128     if (hole_check_mode == HoleCheckMode::kRequired) {
   2129       Label assign;
   2130       __ lw(a3, location);
   2131       __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
   2132       __ Branch(&assign, ne, a3, Operand(t0));
   2133       __ li(a3, Operand(var->name()));
   2134       __ push(a3);
   2135       __ CallRuntime(Runtime::kThrowReferenceError);
   2136       __ bind(&assign);
   2137     }
   2138     if (var->mode() != CONST) {
   2139       EmitStoreToStackLocalOrContextSlot(var, location);
   2140     } else if (var->throw_on_const_assignment(language_mode())) {
   2141       __ CallRuntime(Runtime::kThrowConstAssignError);
   2142     }
   2143   } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
   2144     // Initializing assignment to const {this} needs a write barrier.
   2145     DCHECK(var->IsStackAllocated() || var->IsContextSlot());
   2146     Label uninitialized_this;
   2147     MemOperand location = VarOperand(var, a1);
   2148     __ lw(a3, location);
   2149     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
   2150     __ Branch(&uninitialized_this, eq, a3, Operand(at));
   2151     __ li(a0, Operand(var->name()));
   2152     __ Push(a0);
   2153     __ CallRuntime(Runtime::kThrowReferenceError);
   2154     __ bind(&uninitialized_this);
   2155     EmitStoreToStackLocalOrContextSlot(var, location);
   2156 
   2157   } else {
   2158     DCHECK(var->mode() != CONST || op == Token::INIT);
   2159     if (var->IsLookupSlot()) {
   2160       // Assignment to var.
   2161       __ Push(var->name());
   2162       __ Push(v0);
   2163       __ CallRuntime(is_strict(language_mode())
   2164                          ? Runtime::kStoreLookupSlot_Strict
   2165                          : Runtime::kStoreLookupSlot_Sloppy);
   2166     } else {
   2167       // Assignment to var or initializing assignment to let/const in harmony
   2168       // mode.
   2169       DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
   2170       MemOperand location = VarOperand(var, a1);
   2171       if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
   2172         // Check for an uninitialized let binding.
   2173         __ lw(a2, location);
   2174         __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
   2175         __ Check(eq, kLetBindingReInitialization, a2, Operand(t0));
   2176       }
   2177       EmitStoreToStackLocalOrContextSlot(var, location);
   2178     }
   2179   }
   2180 }
   2181 
   2182 
   2183 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
   2184   // Assignment to a property, using a named store IC.
   2185   Property* prop = expr->target()->AsProperty();
   2186   DCHECK(prop != NULL);
   2187   DCHECK(prop->key()->IsLiteral());
   2188 
   2189   __ mov(StoreDescriptor::ValueRegister(), result_register());
   2190   PopOperand(StoreDescriptor::ReceiverRegister());
   2191   CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value());
   2192 
   2193   PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   2194   context()->Plug(v0);
   2195 }
   2196 
   2197 
   2198 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
   2199   // Assignment to named property of super.
   2200   // v0 : value
   2201   // stack : receiver ('this'), home_object
   2202   DCHECK(prop != NULL);
   2203   Literal* key = prop->key()->AsLiteral();
   2204   DCHECK(key != NULL);
   2205 
   2206   PushOperand(key->value());
   2207   PushOperand(v0);
   2208   CallRuntimeWithOperands(is_strict(language_mode())
   2209                               ? Runtime::kStoreToSuper_Strict
   2210                               : Runtime::kStoreToSuper_Sloppy);
   2211 }
   2212 
   2213 
   2214 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
   2215   // Assignment to named property of super.
   2216   // v0 : value
   2217   // stack : receiver ('this'), home_object, key
   2218   DCHECK(prop != NULL);
   2219 
   2220   PushOperand(v0);
   2221   CallRuntimeWithOperands(is_strict(language_mode())
   2222                               ? Runtime::kStoreKeyedToSuper_Strict
   2223                               : Runtime::kStoreKeyedToSuper_Sloppy);
   2224 }
   2225 
   2226 
   2227 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
   2228   // Assignment to a property, using a keyed store IC.
   2229   // Call keyed store IC.
   2230   // The arguments are:
   2231   // - a0 is the value,
   2232   // - a1 is the key,
   2233   // - a2 is the receiver.
   2234   __ mov(StoreDescriptor::ValueRegister(), result_register());
   2235   PopOperands(StoreDescriptor::ReceiverRegister(),
   2236               StoreDescriptor::NameRegister());
   2237   DCHECK(StoreDescriptor::ValueRegister().is(a0));
   2238 
   2239   CallKeyedStoreIC(expr->AssignmentSlot());
   2240 
   2241   PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   2242   context()->Plug(v0);
   2243 }
   2244 
   2245 // Code common for calls using the IC.
   2246 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
   2247   Expression* callee = expr->expression();
   2248 
   2249   // Get the target function.
   2250   ConvertReceiverMode convert_mode;
   2251   if (callee->IsVariableProxy()) {
   2252     { StackValueContext context(this);
   2253       EmitVariableLoad(callee->AsVariableProxy());
   2254       PrepareForBailout(callee, BailoutState::NO_REGISTERS);
   2255     }
   2256     // Push undefined as receiver. This is patched in the method prologue if it
   2257     // is a sloppy mode method.
   2258     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
   2259     PushOperand(at);
   2260     convert_mode = ConvertReceiverMode::kNullOrUndefined;
   2261   } else {
   2262     // Load the function from the receiver.
   2263     DCHECK(callee->IsProperty());
   2264     DCHECK(!callee->AsProperty()->IsSuperAccess());
   2265     __ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   2266     EmitNamedPropertyLoad(callee->AsProperty());
   2267     PrepareForBailoutForId(callee->AsProperty()->LoadId(),
   2268                            BailoutState::TOS_REGISTER);
   2269     // Push the target function under the receiver.
   2270     __ lw(at, MemOperand(sp, 0));
   2271     PushOperand(at);
   2272     __ sw(v0, MemOperand(sp, kPointerSize));
   2273     convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
   2274   }
   2275 
   2276   EmitCall(expr, convert_mode);
   2277 }
   2278 
   2279 
   2280 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   2281   SetExpressionPosition(expr);
   2282   Expression* callee = expr->expression();
   2283   DCHECK(callee->IsProperty());
   2284   Property* prop = callee->AsProperty();
   2285   DCHECK(prop->IsSuperAccess());
   2286 
   2287   Literal* key = prop->key()->AsLiteral();
   2288   DCHECK(!key->value()->IsSmi());
   2289   // Load the function from the receiver.
   2290   const Register scratch = a1;
   2291   SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   2292   VisitForAccumulatorValue(super_ref->home_object());
   2293   __ mov(scratch, v0);
   2294   VisitForAccumulatorValue(super_ref->this_var());
   2295   PushOperands(scratch, v0, v0, scratch);
   2296   PushOperand(key->value());
   2297 
   2298   // Stack here:
   2299   //  - home_object
   2300   //  - this (receiver)
   2301   //  - this (receiver) <-- LoadFromSuper will pop here and below.
   2302   //  - home_object
   2303   //  - key
   2304   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
   2305   PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   2306 
   2307   // Replace home_object with target function.
   2308   __ sw(v0, MemOperand(sp, kPointerSize));
   2309 
   2310   // Stack here:
   2311   // - target function
   2312   // - this (receiver)
   2313   EmitCall(expr);
   2314 }
   2315 
   2316 
   2317 // Code common for calls using the IC.
   2318 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
   2319                                                 Expression* key) {
   2320   // Load the key.
   2321   VisitForAccumulatorValue(key);
   2322 
   2323   Expression* callee = expr->expression();
   2324 
   2325   // Load the function from the receiver.
   2326   DCHECK(callee->IsProperty());
   2327   __ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   2328   __ Move(LoadDescriptor::NameRegister(), v0);
   2329   EmitKeyedPropertyLoad(callee->AsProperty());
   2330   PrepareForBailoutForId(callee->AsProperty()->LoadId(),
   2331                          BailoutState::TOS_REGISTER);
   2332 
   2333   // Push the target function under the receiver.
   2334   __ lw(at, MemOperand(sp, 0));
   2335   PushOperand(at);
   2336   __ sw(v0, MemOperand(sp, kPointerSize));
   2337 
   2338   EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
   2339 }
   2340 
   2341 
   2342 void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   2343   Expression* callee = expr->expression();
   2344   DCHECK(callee->IsProperty());
   2345   Property* prop = callee->AsProperty();
   2346   DCHECK(prop->IsSuperAccess());
   2347 
   2348   SetExpressionPosition(prop);
   2349   // Load the function from the receiver.
   2350   const Register scratch = a1;
   2351   SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   2352   VisitForAccumulatorValue(super_ref->home_object());
   2353   __ Move(scratch, v0);
   2354   VisitForAccumulatorValue(super_ref->this_var());
   2355   PushOperands(scratch, v0, v0, scratch);
   2356   VisitForStackValue(prop->key());
   2357 
   2358   // Stack here:
   2359   //  - home_object
   2360   //  - this (receiver)
   2361   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
   2362   //  - home_object
   2363   //  - key
   2364   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
   2365   PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   2366 
   2367   // Replace home_object with target function.
   2368   __ sw(v0, MemOperand(sp, kPointerSize));
   2369 
   2370   // Stack here:
   2371   // - target function
   2372   // - this (receiver)
   2373   EmitCall(expr);
   2374 }
   2375 
   2376 
   2377 void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
   2378   // Load the arguments.
   2379   ZoneList<Expression*>* args = expr->arguments();
   2380   int arg_count = args->length();
   2381   for (int i = 0; i < arg_count; i++) {
   2382     VisitForStackValue(args->at(i));
   2383   }
   2384 
   2385   PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   2386   // Record source position of the IC call.
   2387   SetCallPosition(expr, expr->tail_call_mode());
   2388   if (expr->tail_call_mode() == TailCallMode::kAllow) {
   2389     if (FLAG_trace) {
   2390       __ CallRuntime(Runtime::kTraceTailCall);
   2391     }
   2392     // Update profiling counters before the tail call since we will
   2393     // not return to this function.
   2394     EmitProfilingCounterHandlingForReturnSequence(true);
   2395   }
   2396   Handle<Code> code =
   2397       CodeFactory::CallIC(isolate(), mode, expr->tail_call_mode()).code();
   2398   __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
   2399   __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2400   __ li(a0, Operand(arg_count));
   2401   CallIC(code);
   2402   OperandStackDepthDecrement(arg_count + 1);
   2403 
   2404   RecordJSReturnSite(expr);
   2405   RestoreContext();
   2406   context()->DropAndPlug(1, v0);
   2407 }
   2408 
   2409 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
   2410   int arg_count = expr->arguments()->length();
   2411   // t4: copy of the first argument or undefined if it doesn't exist.
   2412   if (arg_count > 0) {
   2413     __ lw(t4, MemOperand(sp, arg_count * kPointerSize));
   2414   } else {
   2415     __ LoadRoot(t4, Heap::kUndefinedValueRootIndex);
   2416   }
   2417 
   2418   // t3: the receiver of the enclosing function.
   2419   __ lw(t3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   2420 
   2421   // t2: the language mode.
   2422   __ li(t2, Operand(Smi::FromInt(language_mode())));
   2423 
   2424   // t1: the start position of the scope the calls resides in.
   2425   __ li(t1, Operand(Smi::FromInt(scope()->start_position())));
   2426 
   2427   // t0: the source position of the eval call.
   2428   __ li(t0, Operand(Smi::FromInt(expr->position())));
   2429 
   2430   // Do the runtime call.
   2431   __ Push(t4, t3, t2, t1, t0);
   2432   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
   2433 }
   2434 
   2435 
   2436 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
   2437 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
   2438   VariableProxy* callee = expr->expression()->AsVariableProxy();
   2439   if (callee->var()->IsLookupSlot()) {
   2440     Label slow, done;
   2441 
   2442     SetExpressionPosition(callee);
   2443     // Generate code for loading from variables potentially shadowed by
   2444     // eval-introduced variables.
   2445     EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
   2446 
   2447     __ bind(&slow);
   2448     // Call the runtime to find the function to call (returned in v0)
   2449     // and the object holding it (returned in v1).
   2450     __ Push(callee->name());
   2451     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
   2452     PushOperands(v0, v1);  // Function, receiver.
   2453     PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
   2454 
   2455     // If fast case code has been generated, emit code to push the
   2456     // function and receiver and have the slow path jump around this
   2457     // code.
   2458     if (done.is_linked()) {
   2459       Label call;
   2460       __ Branch(&call);
   2461       __ bind(&done);
   2462       // Push function.
   2463       __ push(v0);
   2464       // The receiver is implicitly the global receiver. Indicate this
   2465       // by passing the hole to the call function stub.
   2466       __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
   2467       __ push(a1);
   2468       __ bind(&call);
   2469     }
   2470   } else {
   2471     VisitForStackValue(callee);
   2472     // refEnv.WithBaseObject()
   2473     __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
   2474     PushOperand(a2);  // Reserved receiver slot.
   2475   }
   2476 }
   2477 
   2478 
   2479 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
   2480   // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
   2481   // to resolve the function we need to call.  Then we call the resolved
   2482   // function using the given arguments.
   2483   ZoneList<Expression*>* args = expr->arguments();
   2484   int arg_count = args->length();
   2485   PushCalleeAndWithBaseObject(expr);
   2486 
   2487   // Push the arguments.
   2488   for (int i = 0; i < arg_count; i++) {
   2489     VisitForStackValue(args->at(i));
   2490   }
   2491 
   2492   // Push a copy of the function (found below the arguments) and
   2493   // resolve eval.
   2494   __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2495   __ push(a1);
   2496   EmitResolvePossiblyDirectEval(expr);
   2497 
   2498   // Touch up the stack with the resolved function.
   2499   __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2500 
   2501   PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
   2502   // Record source position for debugger.
   2503   SetCallPosition(expr);
   2504   Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny,
   2505                                           expr->tail_call_mode())
   2506                           .code();
   2507   __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
   2508   __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2509   __ li(a0, Operand(arg_count));
   2510   __ Call(code, RelocInfo::CODE_TARGET);
   2511   OperandStackDepthDecrement(arg_count + 1);
   2512   RecordJSReturnSite(expr);
   2513   RestoreContext();
   2514   context()->DropAndPlug(1, v0);
   2515 }
   2516 
   2517 
   2518 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
   2519   Comment cmnt(masm_, "[ CallNew");
   2520   // According to ECMA-262, section 11.2.2, page 44, the function
   2521   // expression in new calls must be evaluated before the
   2522   // arguments.
   2523 
   2524   // Push constructor on the stack.  If it's not a function it's used as
   2525   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
   2526   // ignored.g
   2527   DCHECK(!expr->expression()->IsSuperPropertyReference());
   2528   VisitForStackValue(expr->expression());
   2529 
   2530   // Push the arguments ("left-to-right") on the stack.
   2531   ZoneList<Expression*>* args = expr->arguments();
   2532   int arg_count = args->length();
   2533   for (int i = 0; i < arg_count; i++) {
   2534     VisitForStackValue(args->at(i));
   2535   }
   2536 
   2537   // Call the construct call builtin that handles allocation and
   2538   // constructor invocation.
   2539   SetConstructCallPosition(expr);
   2540 
   2541   // Load function and argument count into a1 and a0.
   2542   __ li(a0, Operand(arg_count));
   2543   __ lw(a1, MemOperand(sp, arg_count * kPointerSize));
   2544 
   2545   // Record call targets in unoptimized code.
   2546   __ EmitLoadTypeFeedbackVector(a2);
   2547   __ li(a3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot())));
   2548 
   2549   CallConstructStub stub(isolate());
   2550   CallIC(stub.GetCode());
   2551   OperandStackDepthDecrement(arg_count + 1);
   2552   PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
   2553   RestoreContext();
   2554   context()->Plug(v0);
   2555 }
   2556 
   2557 
   2558 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
   2559   SuperCallReference* super_call_ref =
   2560       expr->expression()->AsSuperCallReference();
   2561   DCHECK_NOT_NULL(super_call_ref);
   2562 
   2563   // Push the super constructor target on the stack (may be null,
   2564   // but the Construct builtin can deal with that properly).
   2565   VisitForAccumulatorValue(super_call_ref->this_function_var());
   2566   __ AssertFunction(result_register());
   2567   __ lw(result_register(),
   2568         FieldMemOperand(result_register(), HeapObject::kMapOffset));
   2569   __ lw(result_register(),
   2570         FieldMemOperand(result_register(), Map::kPrototypeOffset));
   2571   PushOperand(result_register());
   2572 
   2573   // Push the arguments ("left-to-right") on the stack.
   2574   ZoneList<Expression*>* args = expr->arguments();
   2575   int arg_count = args->length();
   2576   for (int i = 0; i < arg_count; i++) {
   2577     VisitForStackValue(args->at(i));
   2578   }
   2579 
   2580   // Call the construct call builtin that handles allocation and
   2581   // constructor invocation.
   2582   SetConstructCallPosition(expr);
   2583 
   2584   // Load new target into a3.
   2585   VisitForAccumulatorValue(super_call_ref->new_target_var());
   2586   __ mov(a3, result_register());
   2587 
   2588   // Load function and argument count into a1 and a0.
   2589   __ li(a0, Operand(arg_count));
   2590   __ lw(a1, MemOperand(sp, arg_count * kPointerSize));
   2591 
   2592   __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
   2593   OperandStackDepthDecrement(arg_count + 1);
   2594 
   2595   RecordJSReturnSite(expr);
   2596   RestoreContext();
   2597   context()->Plug(v0);
   2598 }
   2599 
   2600 
   2601 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
   2602   ZoneList<Expression*>* args = expr->arguments();
   2603   DCHECK(args->length() == 1);
   2604 
   2605   VisitForAccumulatorValue(args->at(0));
   2606 
   2607   Label materialize_true, materialize_false;
   2608   Label* if_true = NULL;
   2609   Label* if_false = NULL;
   2610   Label* fall_through = NULL;
   2611   context()->PrepareTest(&materialize_true, &materialize_false,
   2612                          &if_true, &if_false, &fall_through);
   2613 
   2614   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2615   __ SmiTst(v0, t0);
   2616   Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through);
   2617 
   2618   context()->Plug(if_true, if_false);
   2619 }
   2620 
   2621 
   2622 void FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
   2623   ZoneList<Expression*>* args = expr->arguments();
   2624   DCHECK(args->length() == 1);
   2625 
   2626   VisitForAccumulatorValue(args->at(0));
   2627 
   2628   Label materialize_true, materialize_false;
   2629   Label* if_true = NULL;
   2630   Label* if_false = NULL;
   2631   Label* fall_through = NULL;
   2632   context()->PrepareTest(&materialize_true, &materialize_false,
   2633                          &if_true, &if_false, &fall_through);
   2634 
   2635   __ JumpIfSmi(v0, if_false);
   2636   __ GetObjectType(v0, a1, a1);
   2637   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2638   Split(ge, a1, Operand(FIRST_JS_RECEIVER_TYPE),
   2639         if_true, if_false, fall_through);
   2640 
   2641   context()->Plug(if_true, if_false);
   2642 }
   2643 
   2644 
   2645 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
   2646   ZoneList<Expression*>* args = expr->arguments();
   2647   DCHECK(args->length() == 1);
   2648 
   2649   VisitForAccumulatorValue(args->at(0));
   2650 
   2651   Label materialize_true, materialize_false;
   2652   Label* if_true = NULL;
   2653   Label* if_false = NULL;
   2654   Label* fall_through = NULL;
   2655   context()->PrepareTest(&materialize_true, &materialize_false,
   2656                          &if_true, &if_false, &fall_through);
   2657 
   2658   __ JumpIfSmi(v0, if_false);
   2659   __ GetObjectType(v0, a1, a1);
   2660   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2661   Split(eq, a1, Operand(JS_ARRAY_TYPE),
   2662         if_true, if_false, fall_through);
   2663 
   2664   context()->Plug(if_true, if_false);
   2665 }
   2666 
   2667 
   2668 void FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
   2669   ZoneList<Expression*>* args = expr->arguments();
   2670   DCHECK(args->length() == 1);
   2671 
   2672   VisitForAccumulatorValue(args->at(0));
   2673 
   2674   Label materialize_true, materialize_false;
   2675   Label* if_true = NULL;
   2676   Label* if_false = NULL;
   2677   Label* fall_through = NULL;
   2678   context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
   2679                          &if_false, &fall_through);
   2680 
   2681   __ JumpIfSmi(v0, if_false);
   2682   __ GetObjectType(v0, a1, a1);
   2683   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2684   Split(eq, a1, Operand(JS_TYPED_ARRAY_TYPE), if_true, if_false, fall_through);
   2685 
   2686   context()->Plug(if_true, if_false);
   2687 }
   2688 
   2689 
   2690 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
   2691   ZoneList<Expression*>* args = expr->arguments();
   2692   DCHECK(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(v0, if_false);
   2704   __ GetObjectType(v0, a1, a1);
   2705   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2706   Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through);
   2707 
   2708   context()->Plug(if_true, if_false);
   2709 }
   2710 
   2711 
   2712 void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
   2713   ZoneList<Expression*>* args = expr->arguments();
   2714   DCHECK(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, &if_true,
   2723                          &if_false, &fall_through);
   2724 
   2725   __ JumpIfSmi(v0, if_false);
   2726   __ GetObjectType(v0, a1, a1);
   2727   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   2728   Split(eq, a1, Operand(JS_PROXY_TYPE), if_true, if_false, fall_through);
   2729 
   2730   context()->Plug(if_true, if_false);
   2731 }
   2732 
   2733 
   2734 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
   2735   ZoneList<Expression*>* args = expr->arguments();
   2736   DCHECK(args->length() == 1);
   2737   Label done, null, function, non_function_constructor;
   2738 
   2739   VisitForAccumulatorValue(args->at(0));
   2740 
   2741   // If the object is not a JSReceiver, we return null.
   2742   __ JumpIfSmi(v0, &null);
   2743   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   2744   __ GetObjectType(v0, v0, a1);  // Map is now in v0.
   2745   __ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
   2746 
   2747   // Return 'Function' for JSFunction and JSBoundFunction objects.
   2748   STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
   2749   __ Branch(&function, hs, a1, Operand(FIRST_FUNCTION_TYPE));
   2750 
   2751   // Check if the constructor in the map is a JS function.
   2752   Register instance_type = a2;
   2753   __ GetMapConstructor(v0, v0, a1, instance_type);
   2754   __ Branch(&non_function_constructor, ne, instance_type,
   2755             Operand(JS_FUNCTION_TYPE));
   2756 
   2757   // v0 now contains the constructor function. Grab the
   2758   // instance class name from there.
   2759   __ lw(v0, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset));
   2760   __ lw(v0, FieldMemOperand(v0, SharedFunctionInfo::kInstanceClassNameOffset));
   2761   __ Branch(&done);
   2762 
   2763   // Functions have class 'Function'.
   2764   __ bind(&function);
   2765   __ LoadRoot(v0, Heap::kFunction_stringRootIndex);
   2766   __ jmp(&done);
   2767 
   2768   // Objects with a non-function constructor have class 'Object'.
   2769   __ bind(&non_function_constructor);
   2770   __ LoadRoot(v0, Heap::kObject_stringRootIndex);
   2771   __ jmp(&done);
   2772 
   2773   // Non-JS objects have class null.
   2774   __ bind(&null);
   2775   __ LoadRoot(v0, Heap::kNullValueRootIndex);
   2776 
   2777   // All done.
   2778   __ bind(&done);
   2779 
   2780   context()->Plug(v0);
   2781 }
   2782 
   2783 
   2784 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
   2785   ZoneList<Expression*>* args = expr->arguments();
   2786   DCHECK(args->length() == 2);
   2787 
   2788   VisitForStackValue(args->at(0));
   2789   VisitForAccumulatorValue(args->at(1));
   2790   __ mov(a0, result_register());
   2791 
   2792   Register object = a1;
   2793   Register index = a0;
   2794   Register result = v0;
   2795 
   2796   PopOperand(object);
   2797 
   2798   Label need_conversion;
   2799   Label index_out_of_range;
   2800   Label done;
   2801   StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
   2802                                       &need_conversion, &index_out_of_range);
   2803   generator.GenerateFast(masm_);
   2804   __ jmp(&done);
   2805 
   2806   __ bind(&index_out_of_range);
   2807   // When the index is out of range, the spec requires us to return
   2808   // NaN.
   2809   __ LoadRoot(result, Heap::kNanValueRootIndex);
   2810   __ jmp(&done);
   2811 
   2812   __ bind(&need_conversion);
   2813   // Load the undefined value into the result register, which will
   2814   // trigger conversion.
   2815   __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
   2816   __ jmp(&done);
   2817 
   2818   NopRuntimeCallHelper call_helper;
   2819   generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
   2820 
   2821   __ bind(&done);
   2822   context()->Plug(result);
   2823 }
   2824 
   2825 
   2826 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   2827   ZoneList<Expression*>* args = expr->arguments();
   2828   DCHECK_LE(2, args->length());
   2829   // Push target, receiver and arguments onto the stack.
   2830   for (Expression* const arg : *args) {
   2831     VisitForStackValue(arg);
   2832   }
   2833   PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   2834   // Move target to a1.
   2835   int const argc = args->length() - 2;
   2836   __ lw(a1, MemOperand(sp, (argc + 1) * kPointerSize));
   2837   // Call the target.
   2838   __ li(a0, Operand(argc));
   2839   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   2840   OperandStackDepthDecrement(argc + 1);
   2841   RestoreContext();
   2842   // Discard the function left on TOS.
   2843   context()->DropAndPlug(1, v0);
   2844 }
   2845 
   2846 void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
   2847   ZoneList<Expression*>* args = expr->arguments();
   2848   DCHECK_EQ(1, args->length());
   2849   VisitForAccumulatorValue(args->at(0));
   2850   __ AssertFunction(v0);
   2851   __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
   2852   __ lw(v0, FieldMemOperand(v0, Map::kPrototypeOffset));
   2853   context()->Plug(v0);
   2854 }
   2855 
   2856 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   2857   DCHECK(expr->arguments()->length() == 0);
   2858   ExternalReference debug_is_active =
   2859       ExternalReference::debug_is_active_address(isolate());
   2860   __ li(at, Operand(debug_is_active));
   2861   __ lb(v0, MemOperand(at));
   2862   __ SmiTag(v0);
   2863   context()->Plug(v0);
   2864 }
   2865 
   2866 
   2867 void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
   2868   ZoneList<Expression*>* args = expr->arguments();
   2869   DCHECK_EQ(2, args->length());
   2870   VisitForStackValue(args->at(0));
   2871   VisitForStackValue(args->at(1));
   2872 
   2873   Label runtime, done;
   2874 
   2875   __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &runtime,
   2876               NO_ALLOCATION_FLAGS);
   2877   __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, a1);
   2878   __ Pop(a2, a3);
   2879   __ LoadRoot(t0, Heap::kEmptyFixedArrayRootIndex);
   2880   __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
   2881   __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset));
   2882   __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
   2883   __ sw(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset));
   2884   __ sw(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset));
   2885   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
   2886   __ jmp(&done);
   2887 
   2888   __ bind(&runtime);
   2889   CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
   2890 
   2891   __ bind(&done);
   2892   context()->Plug(v0);
   2893 }
   2894 
   2895 
   2896 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
   2897   // Push function.
   2898   __ LoadNativeContextSlot(expr->context_index(), v0);
   2899   PushOperand(v0);
   2900 
   2901   // Push undefined as the receiver.
   2902   __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
   2903   PushOperand(v0);
   2904 }
   2905 
   2906 
   2907 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
   2908   ZoneList<Expression*>* args = expr->arguments();
   2909   int arg_count = args->length();
   2910 
   2911   SetCallPosition(expr);
   2912   __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   2913   __ li(a0, Operand(arg_count));
   2914   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
   2915           RelocInfo::CODE_TARGET);
   2916   OperandStackDepthDecrement(arg_count + 1);
   2917   RestoreContext();
   2918 }
   2919 
   2920 
   2921 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
   2922   switch (expr->op()) {
   2923     case Token::DELETE: {
   2924       Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
   2925       Property* property = expr->expression()->AsProperty();
   2926       VariableProxy* proxy = expr->expression()->AsVariableProxy();
   2927 
   2928       if (property != NULL) {
   2929         VisitForStackValue(property->obj());
   2930         VisitForStackValue(property->key());
   2931         CallRuntimeWithOperands(is_strict(language_mode())
   2932                                     ? Runtime::kDeleteProperty_Strict
   2933                                     : Runtime::kDeleteProperty_Sloppy);
   2934         context()->Plug(v0);
   2935       } else if (proxy != NULL) {
   2936         Variable* var = proxy->var();
   2937         // Delete of an unqualified identifier is disallowed in strict mode but
   2938         // "delete this" is allowed.
   2939         bool is_this = var->is_this();
   2940         DCHECK(is_sloppy(language_mode()) || is_this);
   2941         if (var->IsUnallocated()) {
   2942           __ LoadGlobalObject(a2);
   2943           __ li(a1, Operand(var->name()));
   2944           __ Push(a2, a1);
   2945           __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
   2946           context()->Plug(v0);
   2947         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
   2948           // Result of deleting non-global, non-dynamic variables is false.
   2949           // The subexpression does not have side effects.
   2950           context()->Plug(is_this);
   2951         } else {
   2952           // Non-global variable.  Call the runtime to try to delete from the
   2953           // context where the variable was introduced.
   2954           __ Push(var->name());
   2955           __ CallRuntime(Runtime::kDeleteLookupSlot);
   2956           context()->Plug(v0);
   2957         }
   2958       } else {
   2959         // Result of deleting non-property, non-variable reference is true.
   2960         // The subexpression may have side effects.
   2961         VisitForEffect(expr->expression());
   2962         context()->Plug(true);
   2963       }
   2964       break;
   2965     }
   2966 
   2967     case Token::VOID: {
   2968       Comment cmnt(masm_, "[ UnaryOperation (VOID)");
   2969       VisitForEffect(expr->expression());
   2970       context()->Plug(Heap::kUndefinedValueRootIndex);
   2971       break;
   2972     }
   2973 
   2974     case Token::NOT: {
   2975       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
   2976       if (context()->IsEffect()) {
   2977         // Unary NOT has no side effects so it's only necessary to visit the
   2978         // subexpression.  Match the optimizing compiler by not branching.
   2979         VisitForEffect(expr->expression());
   2980       } else if (context()->IsTest()) {
   2981         const TestContext* test = TestContext::cast(context());
   2982         // The labels are swapped for the recursive call.
   2983         VisitForControl(expr->expression(),
   2984                         test->false_label(),
   2985                         test->true_label(),
   2986                         test->fall_through());
   2987         context()->Plug(test->true_label(), test->false_label());
   2988       } else {
   2989         // We handle value contexts explicitly rather than simply visiting
   2990         // for control and plugging the control flow into the context,
   2991         // because we need to prepare a pair of extra administrative AST ids
   2992         // for the optimizing compiler.
   2993         DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
   2994         Label materialize_true, materialize_false, done;
   2995         VisitForControl(expr->expression(),
   2996                         &materialize_false,
   2997                         &materialize_true,
   2998                         &materialize_true);
   2999         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
   3000         __ bind(&materialize_true);
   3001         PrepareForBailoutForId(expr->MaterializeTrueId(),
   3002                                BailoutState::NO_REGISTERS);
   3003         __ LoadRoot(v0, Heap::kTrueValueRootIndex);
   3004         if (context()->IsStackValue()) __ push(v0);
   3005         __ jmp(&done);
   3006         __ bind(&materialize_false);
   3007         PrepareForBailoutForId(expr->MaterializeFalseId(),
   3008                                BailoutState::NO_REGISTERS);
   3009         __ LoadRoot(v0, Heap::kFalseValueRootIndex);
   3010         if (context()->IsStackValue()) __ push(v0);
   3011         __ bind(&done);
   3012       }
   3013       break;
   3014     }
   3015 
   3016     case Token::TYPEOF: {
   3017       Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
   3018       {
   3019         AccumulatorValueContext context(this);
   3020         VisitForTypeofValue(expr->expression());
   3021       }
   3022       __ mov(a3, v0);
   3023       __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET);
   3024       context()->Plug(v0);
   3025       break;
   3026     }
   3027 
   3028     default:
   3029       UNREACHABLE();
   3030   }
   3031 }
   3032 
   3033 
   3034 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
   3035   DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
   3036 
   3037   Comment cmnt(masm_, "[ CountOperation");
   3038 
   3039   Property* prop = expr->expression()->AsProperty();
   3040   LhsKind assign_type = Property::GetAssignType(prop);
   3041 
   3042   // Evaluate expression and get value.
   3043   if (assign_type == VARIABLE) {
   3044     DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
   3045     AccumulatorValueContext context(this);
   3046     EmitVariableLoad(expr->expression()->AsVariableProxy());
   3047   } else {
   3048     // Reserve space for result of postfix operation.
   3049     if (expr->is_postfix() && !context()->IsEffect()) {
   3050       __ li(at, Operand(Smi::kZero));
   3051       PushOperand(at);
   3052     }
   3053     switch (assign_type) {
   3054       case NAMED_PROPERTY: {
   3055         // Put the object both on the stack and in the register.
   3056         VisitForStackValue(prop->obj());
   3057         __ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   3058         EmitNamedPropertyLoad(prop);
   3059         break;
   3060       }
   3061 
   3062       case NAMED_SUPER_PROPERTY: {
   3063         VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
   3064         VisitForAccumulatorValue(
   3065             prop->obj()->AsSuperPropertyReference()->home_object());
   3066         const Register scratch = a1;
   3067         __ lw(scratch, MemOperand(sp, 0));  // this
   3068         PushOperands(result_register(), scratch, result_register());
   3069         EmitNamedSuperPropertyLoad(prop);
   3070         break;
   3071       }
   3072 
   3073       case KEYED_SUPER_PROPERTY: {
   3074         VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
   3075         VisitForStackValue(
   3076             prop->obj()->AsSuperPropertyReference()->home_object());
   3077         VisitForAccumulatorValue(prop->key());
   3078         const Register scratch1 = a1;
   3079         const Register scratch2 = t0;
   3080         __ lw(scratch1, MemOperand(sp, 1 * kPointerSize));  // this
   3081         __ lw(scratch2, MemOperand(sp, 0 * kPointerSize));  // home object
   3082         PushOperands(result_register(), scratch1, scratch2, result_register());
   3083         EmitKeyedSuperPropertyLoad(prop);
   3084         break;
   3085       }
   3086 
   3087       case KEYED_PROPERTY: {
   3088         VisitForStackValue(prop->obj());
   3089         VisitForStackValue(prop->key());
   3090         __ lw(LoadDescriptor::ReceiverRegister(),
   3091               MemOperand(sp, 1 * kPointerSize));
   3092         __ lw(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
   3093         EmitKeyedPropertyLoad(prop);
   3094         break;
   3095       }
   3096 
   3097       case VARIABLE:
   3098         UNREACHABLE();
   3099     }
   3100   }
   3101 
   3102   // We need a second deoptimization point after loading the value
   3103   // in case evaluating the property load my have a side effect.
   3104   if (assign_type == VARIABLE) {
   3105     PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   3106   } else {
   3107     PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   3108   }
   3109 
   3110   // Inline smi case if we are in a loop.
   3111   Label stub_call, done;
   3112   JumpPatchSite patch_site(masm_);
   3113 
   3114   int count_value = expr->op() == Token::INC ? 1 : -1;
   3115   __ mov(a0, v0);
   3116   if (ShouldInlineSmiCase(expr->op())) {
   3117     Label slow;
   3118     patch_site.EmitJumpIfNotSmi(v0, &slow);
   3119 
   3120     // Save result for postfix expressions.
   3121     if (expr->is_postfix()) {
   3122       if (!context()->IsEffect()) {
   3123         // Save the result on the stack. If we have a named or keyed property
   3124         // we store the result under the receiver that is currently on top
   3125         // of the stack.
   3126         switch (assign_type) {
   3127           case VARIABLE:
   3128             __ push(v0);
   3129             break;
   3130           case NAMED_PROPERTY:
   3131             __ sw(v0, MemOperand(sp, kPointerSize));
   3132             break;
   3133           case NAMED_SUPER_PROPERTY:
   3134             __ sw(v0, MemOperand(sp, 2 * kPointerSize));
   3135             break;
   3136           case KEYED_PROPERTY:
   3137             __ sw(v0, MemOperand(sp, 2 * kPointerSize));
   3138             break;
   3139           case KEYED_SUPER_PROPERTY:
   3140             __ sw(v0, MemOperand(sp, 3 * kPointerSize));
   3141             break;
   3142         }
   3143       }
   3144     }
   3145 
   3146     Register scratch1 = a1;
   3147     __ li(scratch1, Operand(Smi::FromInt(count_value)));
   3148     __ AddBranchNoOvf(v0, v0, Operand(scratch1), &done);
   3149     // Call stub. Undo operation first.
   3150     __ Move(v0, a0);
   3151     __ jmp(&stub_call);
   3152     __ bind(&slow);
   3153   }
   3154 
   3155   // Convert old value into a number.
   3156   __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
   3157   RestoreContext();
   3158   PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
   3159 
   3160   // Save result for postfix expressions.
   3161   if (expr->is_postfix()) {
   3162     if (!context()->IsEffect()) {
   3163       // Save the result on the stack. If we have a named or keyed property
   3164       // we store the result under the receiver that is currently on top
   3165       // of the stack.
   3166       switch (assign_type) {
   3167         case VARIABLE:
   3168           PushOperand(v0);
   3169           break;
   3170         case NAMED_PROPERTY:
   3171           __ sw(v0, MemOperand(sp, kPointerSize));
   3172           break;
   3173         case NAMED_SUPER_PROPERTY:
   3174           __ sw(v0, MemOperand(sp, 2 * kPointerSize));
   3175           break;
   3176         case KEYED_PROPERTY:
   3177           __ sw(v0, MemOperand(sp, 2 * kPointerSize));
   3178           break;
   3179         case KEYED_SUPER_PROPERTY:
   3180           __ sw(v0, MemOperand(sp, 3 * kPointerSize));
   3181           break;
   3182       }
   3183     }
   3184   }
   3185 
   3186   __ bind(&stub_call);
   3187   __ mov(a1, v0);
   3188   __ li(a0, Operand(Smi::FromInt(count_value)));
   3189 
   3190   SetExpressionPosition(expr);
   3191 
   3192   Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
   3193   CallIC(code, expr->CountBinOpFeedbackId());
   3194   patch_site.EmitPatchInfo();
   3195   __ bind(&done);
   3196 
   3197   // Store the value returned in v0.
   3198   switch (assign_type) {
   3199     case VARIABLE: {
   3200       VariableProxy* proxy = expr->expression()->AsVariableProxy();
   3201       if (expr->is_postfix()) {
   3202         { EffectContext context(this);
   3203           EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
   3204                                  proxy->hole_check_mode());
   3205           PrepareForBailoutForId(expr->AssignmentId(),
   3206                                  BailoutState::TOS_REGISTER);
   3207           context.Plug(v0);
   3208         }
   3209         // For all contexts except EffectConstant we have the result on
   3210         // top of the stack.
   3211         if (!context()->IsEffect()) {
   3212           context()->PlugTOS();
   3213         }
   3214       } else {
   3215         EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
   3216                                proxy->hole_check_mode());
   3217         PrepareForBailoutForId(expr->AssignmentId(),
   3218                                BailoutState::TOS_REGISTER);
   3219         context()->Plug(v0);
   3220       }
   3221       break;
   3222     }
   3223     case NAMED_PROPERTY: {
   3224       __ mov(StoreDescriptor::ValueRegister(), result_register());
   3225       PopOperand(StoreDescriptor::ReceiverRegister());
   3226       CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value());
   3227       PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   3228       if (expr->is_postfix()) {
   3229         if (!context()->IsEffect()) {
   3230           context()->PlugTOS();
   3231         }
   3232       } else {
   3233         context()->Plug(v0);
   3234       }
   3235       break;
   3236     }
   3237     case NAMED_SUPER_PROPERTY: {
   3238       EmitNamedSuperPropertyStore(prop);
   3239       PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   3240       if (expr->is_postfix()) {
   3241         if (!context()->IsEffect()) {
   3242           context()->PlugTOS();
   3243         }
   3244       } else {
   3245         context()->Plug(v0);
   3246       }
   3247       break;
   3248     }
   3249     case KEYED_SUPER_PROPERTY: {
   3250       EmitKeyedSuperPropertyStore(prop);
   3251       PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   3252       if (expr->is_postfix()) {
   3253         if (!context()->IsEffect()) {
   3254           context()->PlugTOS();
   3255         }
   3256       } else {
   3257         context()->Plug(v0);
   3258       }
   3259       break;
   3260     }
   3261     case KEYED_PROPERTY: {
   3262       __ mov(StoreDescriptor::ValueRegister(), result_register());
   3263       PopOperands(StoreDescriptor::ReceiverRegister(),
   3264                   StoreDescriptor::NameRegister());
   3265       CallKeyedStoreIC(expr->CountSlot());
   3266       PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   3267       if (expr->is_postfix()) {
   3268         if (!context()->IsEffect()) {
   3269           context()->PlugTOS();
   3270         }
   3271       } else {
   3272         context()->Plug(v0);
   3273       }
   3274       break;
   3275     }
   3276   }
   3277 }
   3278 
   3279 
   3280 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
   3281                                                  Expression* sub_expr,
   3282                                                  Handle<String> check) {
   3283   Label materialize_true, materialize_false;
   3284   Label* if_true = NULL;
   3285   Label* if_false = NULL;
   3286   Label* fall_through = NULL;
   3287   context()->PrepareTest(&materialize_true, &materialize_false,
   3288                          &if_true, &if_false, &fall_through);
   3289 
   3290   { AccumulatorValueContext context(this);
   3291     VisitForTypeofValue(sub_expr);
   3292   }
   3293   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   3294 
   3295   Factory* factory = isolate()->factory();
   3296   if (String::Equals(check, factory->number_string())) {
   3297     __ JumpIfSmi(v0, if_true);
   3298     __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
   3299     __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
   3300     Split(eq, v0, Operand(at), if_true, if_false, fall_through);
   3301   } else if (String::Equals(check, factory->string_string())) {
   3302     __ JumpIfSmi(v0, if_false);
   3303     __ GetObjectType(v0, v0, a1);
   3304     Split(lt, a1, Operand(FIRST_NONSTRING_TYPE), if_true, if_false,
   3305           fall_through);
   3306   } else if (String::Equals(check, factory->symbol_string())) {
   3307     __ JumpIfSmi(v0, if_false);
   3308     __ GetObjectType(v0, v0, a1);
   3309     Split(eq, a1, Operand(SYMBOL_TYPE), if_true, if_false, fall_through);
   3310   } else if (String::Equals(check, factory->boolean_string())) {
   3311     __ LoadRoot(at, Heap::kTrueValueRootIndex);
   3312     __ Branch(if_true, eq, v0, Operand(at));
   3313     __ LoadRoot(at, Heap::kFalseValueRootIndex);
   3314     Split(eq, v0, Operand(at), if_true, if_false, fall_through);
   3315   } else if (String::Equals(check, factory->undefined_string())) {
   3316     __ LoadRoot(at, Heap::kNullValueRootIndex);
   3317     __ Branch(if_false, eq, v0, Operand(at));
   3318     __ JumpIfSmi(v0, if_false);
   3319     // Check for undetectable objects => true.
   3320     __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
   3321     __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
   3322     __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
   3323     Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
   3324   } else if (String::Equals(check, factory->function_string())) {
   3325     __ JumpIfSmi(v0, if_false);
   3326     __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
   3327     __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
   3328     __ And(a1, a1,
   3329            Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
   3330     Split(eq, a1, Operand(1 << Map::kIsCallable), if_true, if_false,
   3331           fall_through);
   3332   } else if (String::Equals(check, factory->object_string())) {
   3333     __ JumpIfSmi(v0, if_false);
   3334     __ LoadRoot(at, Heap::kNullValueRootIndex);
   3335     __ Branch(if_true, eq, v0, Operand(at));
   3336     STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   3337     __ GetObjectType(v0, v0, a1);
   3338     __ Branch(if_false, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
   3339     // Check for callable or undetectable objects => false.
   3340     __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
   3341     __ And(a1, a1,
   3342            Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
   3343     Split(eq, a1, Operand(zero_reg), if_true, if_false, fall_through);
   3344 // clang-format off
   3345 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type)    \
   3346   } else if (String::Equals(check, factory->type##_string())) {  \
   3347     __ JumpIfSmi(v0, if_false);                                  \
   3348     __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));      \
   3349     __ LoadRoot(at, Heap::k##Type##MapRootIndex);                \
   3350     Split(eq, v0, Operand(at), if_true, if_false, fall_through);
   3351   SIMD128_TYPES(SIMD128_TYPE)
   3352 #undef SIMD128_TYPE
   3353     // clang-format on
   3354   } else {
   3355     if (if_false != fall_through) __ jmp(if_false);
   3356   }
   3357   context()->Plug(if_true, if_false);
   3358 }
   3359 
   3360 
   3361 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   3362   Comment cmnt(masm_, "[ CompareOperation");
   3363 
   3364   // First we try a fast inlined version of the compare when one of
   3365   // the operands is a literal.
   3366   if (TryLiteralCompare(expr)) return;
   3367 
   3368   // Always perform the comparison for its control flow.  Pack the result
   3369   // into the expression's context after the comparison is performed.
   3370   Label materialize_true, materialize_false;
   3371   Label* if_true = NULL;
   3372   Label* if_false = NULL;
   3373   Label* fall_through = NULL;
   3374   context()->PrepareTest(&materialize_true, &materialize_false,
   3375                          &if_true, &if_false, &fall_through);
   3376 
   3377   Token::Value op = expr->op();
   3378   VisitForStackValue(expr->left());
   3379   switch (op) {
   3380     case Token::IN:
   3381       VisitForStackValue(expr->right());
   3382       SetExpressionPosition(expr);
   3383       EmitHasProperty();
   3384       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
   3385       __ LoadRoot(t0, Heap::kTrueValueRootIndex);
   3386       Split(eq, v0, Operand(t0), if_true, if_false, fall_through);
   3387       break;
   3388 
   3389     case Token::INSTANCEOF: {
   3390       VisitForAccumulatorValue(expr->right());
   3391       SetExpressionPosition(expr);
   3392       __ mov(a0, result_register());
   3393       PopOperand(a1);
   3394       __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET);
   3395       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
   3396       __ LoadRoot(at, Heap::kTrueValueRootIndex);
   3397       Split(eq, v0, Operand(at), if_true, if_false, fall_through);
   3398       break;
   3399     }
   3400 
   3401     default: {
   3402       VisitForAccumulatorValue(expr->right());
   3403       SetExpressionPosition(expr);
   3404       Condition cc = CompareIC::ComputeCondition(op);
   3405       __ mov(a0, result_register());
   3406       PopOperand(a1);
   3407 
   3408       bool inline_smi_code = ShouldInlineSmiCase(op);
   3409       JumpPatchSite patch_site(masm_);
   3410       if (inline_smi_code) {
   3411         Label slow_case;
   3412         __ Or(a2, a0, Operand(a1));
   3413         patch_site.EmitJumpIfNotSmi(a2, &slow_case);
   3414         Split(cc, a1, Operand(a0), if_true, if_false, NULL);
   3415         __ bind(&slow_case);
   3416       }
   3417 
   3418       Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
   3419       CallIC(ic, expr->CompareOperationFeedbackId());
   3420       patch_site.EmitPatchInfo();
   3421       PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   3422       Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
   3423     }
   3424   }
   3425 
   3426   // Convert the result of the comparison into one expected for this
   3427   // expression's context.
   3428   context()->Plug(if_true, if_false);
   3429 }
   3430 
   3431 
   3432 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
   3433                                               Expression* sub_expr,
   3434                                               NilValue nil) {
   3435   Label materialize_true, materialize_false;
   3436   Label* if_true = NULL;
   3437   Label* if_false = NULL;
   3438   Label* fall_through = NULL;
   3439   context()->PrepareTest(&materialize_true, &materialize_false,
   3440                          &if_true, &if_false, &fall_through);
   3441 
   3442   VisitForAccumulatorValue(sub_expr);
   3443   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
   3444   if (expr->op() == Token::EQ_STRICT) {
   3445     Heap::RootListIndex nil_value = nil == kNullValue ?
   3446         Heap::kNullValueRootIndex :
   3447         Heap::kUndefinedValueRootIndex;
   3448     __ LoadRoot(a1, nil_value);
   3449     Split(eq, v0, Operand(a1), if_true, if_false, fall_through);
   3450   } else {
   3451     __ JumpIfSmi(v0, if_false);
   3452     __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
   3453     __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
   3454     __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
   3455     Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
   3456   }
   3457   context()->Plug(if_true, if_false);
   3458 }
   3459 
   3460 
   3461 Register FullCodeGenerator::result_register() {
   3462   return v0;
   3463 }
   3464 
   3465 
   3466 Register FullCodeGenerator::context_register() {
   3467   return cp;
   3468 }
   3469 
   3470 void FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
   3471   DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
   3472   __ lw(value, MemOperand(fp, frame_offset));
   3473 }
   3474 
   3475 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
   3476   DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
   3477   __ sw(value, MemOperand(fp, frame_offset));
   3478 }
   3479 
   3480 
   3481 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
   3482   __ lw(dst, ContextMemOperand(cp, context_index));
   3483 }
   3484 
   3485 
   3486 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
   3487   DeclarationScope* closure_scope = scope()->GetClosureScope();
   3488   if (closure_scope->is_script_scope() ||
   3489       closure_scope->is_module_scope()) {
   3490     // Contexts nested in the native context have a canonical empty function
   3491     // as their closure, not the anonymous closure containing the global
   3492     // code.
   3493     __ LoadNativeContextSlot(Context::CLOSURE_INDEX, at);
   3494   } else if (closure_scope->is_eval_scope()) {
   3495     // Contexts created by a call to eval have the same closure as the
   3496     // context calling eval, not the anonymous closure containing the eval
   3497     // code.  Fetch it from the context.
   3498     __ lw(at, ContextMemOperand(cp, Context::CLOSURE_INDEX));
   3499   } else {
   3500     DCHECK(closure_scope->is_function_scope());
   3501     __ lw(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   3502   }
   3503   PushOperand(at);
   3504 }
   3505 
   3506 
   3507 // ----------------------------------------------------------------------------
   3508 // Non-local control flow support.
   3509 
   3510 void FullCodeGenerator::EnterFinallyBlock() {
   3511   DCHECK(!result_register().is(a1));
   3512   // Store pending message while executing finally block.
   3513   ExternalReference pending_message_obj =
   3514       ExternalReference::address_of_pending_message_obj(isolate());
   3515   __ li(at, Operand(pending_message_obj));
   3516   __ lw(a1, MemOperand(at));
   3517   PushOperand(a1);
   3518 
   3519   ClearPendingMessage();
   3520 }
   3521 
   3522 
   3523 void FullCodeGenerator::ExitFinallyBlock() {
   3524   DCHECK(!result_register().is(a1));
   3525   // Restore pending message from stack.
   3526   PopOperand(a1);
   3527   ExternalReference pending_message_obj =
   3528       ExternalReference::address_of_pending_message_obj(isolate());
   3529   __ li(at, Operand(pending_message_obj));
   3530   __ sw(a1, MemOperand(at));
   3531 }
   3532 
   3533 
   3534 void FullCodeGenerator::ClearPendingMessage() {
   3535   DCHECK(!result_register().is(a1));
   3536   ExternalReference pending_message_obj =
   3537       ExternalReference::address_of_pending_message_obj(isolate());
   3538   __ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
   3539   __ li(at, Operand(pending_message_obj));
   3540   __ sw(a1, MemOperand(at));
   3541 }
   3542 
   3543 
   3544 void FullCodeGenerator::DeferredCommands::EmitCommands() {
   3545   DCHECK(!result_register().is(a1));
   3546   __ Pop(result_register());  // Restore the accumulator.
   3547   __ Pop(a1);                 // Get the token.
   3548   for (DeferredCommand cmd : commands_) {
   3549     Label skip;
   3550     __ li(at, Operand(Smi::FromInt(cmd.token)));
   3551     __ Branch(&skip, ne, a1, Operand(at));
   3552     switch (cmd.command) {
   3553       case kReturn:
   3554         codegen_->EmitUnwindAndReturn();
   3555         break;
   3556       case kThrow:
   3557         __ Push(result_register());
   3558         __ CallRuntime(Runtime::kReThrow);
   3559         break;
   3560       case kContinue:
   3561         codegen_->EmitContinue(cmd.target);
   3562         break;
   3563       case kBreak:
   3564         codegen_->EmitBreak(cmd.target);
   3565         break;
   3566     }
   3567     __ bind(&skip);
   3568   }
   3569 }
   3570 
   3571 #undef __
   3572 
   3573 
   3574 void BackEdgeTable::PatchAt(Code* unoptimized_code,
   3575                             Address pc,
   3576                             BackEdgeState target_state,
   3577                             Code* replacement_code) {
   3578   static const int kInstrSize = Assembler::kInstrSize;
   3579   Address pc_immediate_load_address =
   3580       Assembler::target_address_from_return_address(pc);
   3581   Address branch_address = pc_immediate_load_address - 2 * kInstrSize;
   3582   Isolate* isolate = unoptimized_code->GetIsolate();
   3583   CodePatcher patcher(isolate, branch_address, 1);
   3584 
   3585   switch (target_state) {
   3586     case INTERRUPT:
   3587       // slt at, a3, zero_reg (in case of count based interrupts)
   3588       // beq at, zero_reg, ok
   3589       // lui t9, <interrupt stub address> upper
   3590       // ori t9, <interrupt stub address> lower
   3591       // jalr t9
   3592       // nop
   3593       // ok-label ----- pc_after points here
   3594       patcher.masm()->slt(at, a3, zero_reg);
   3595       break;
   3596     case ON_STACK_REPLACEMENT:
   3597       // addiu at, zero_reg, 1
   3598       // beq at, zero_reg, ok  ;; Not changed
   3599       // lui t9, <on-stack replacement address> upper
   3600       // ori t9, <on-stack replacement address> lower
   3601       // jalr t9  ;; Not changed
   3602       // nop  ;; Not changed
   3603       // ok-label ----- pc_after points here
   3604       patcher.masm()->addiu(at, zero_reg, 1);
   3605       break;
   3606   }
   3607   // Replace the stack check address in the load-immediate (lui/ori pair)
   3608   // with the entry address of the replacement code.
   3609   Assembler::set_target_address_at(isolate, pc_immediate_load_address,
   3610                                    replacement_code->entry());
   3611 
   3612   unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
   3613       unoptimized_code, pc_immediate_load_address, replacement_code);
   3614 }
   3615 
   3616 
   3617 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
   3618     Isolate* isolate,
   3619     Code* unoptimized_code,
   3620     Address pc) {
   3621   static const int kInstrSize = Assembler::kInstrSize;
   3622   Address pc_immediate_load_address =
   3623       Assembler::target_address_from_return_address(pc);
   3624   Address branch_address = pc_immediate_load_address - 2 * kInstrSize;
   3625 
   3626   DCHECK(Assembler::IsBeq(Assembler::instr_at(branch_address + kInstrSize)));
   3627   if (!Assembler::IsAddImmediate(Assembler::instr_at(branch_address))) {
   3628     DCHECK(reinterpret_cast<uint32_t>(
   3629         Assembler::target_address_at(pc_immediate_load_address)) ==
   3630            reinterpret_cast<uint32_t>(
   3631                isolate->builtins()->InterruptCheck()->entry()));
   3632     return INTERRUPT;
   3633   }
   3634 
   3635   DCHECK(Assembler::IsAddImmediate(Assembler::instr_at(branch_address)));
   3636 
   3637   DCHECK(reinterpret_cast<uint32_t>(
   3638              Assembler::target_address_at(pc_immediate_load_address)) ==
   3639          reinterpret_cast<uint32_t>(
   3640              isolate->builtins()->OnStackReplacement()->entry()));
   3641   return ON_STACK_REPLACEMENT;
   3642 }
   3643 
   3644 
   3645 }  // namespace internal
   3646 }  // namespace v8
   3647 
   3648 #endif  // V8_TARGET_ARCH_MIPS
   3649