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