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