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