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