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