full-codegen-ia32.cc revision e0cee9b3ed82e2391fd85d118aeaa4ea361c687d
1086aeeaae12517475c22695a200be45495516549Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
23ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Redistribution and use in source and binary forms, with or without
33ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// modification, are permitted provided that the following conditions are
43ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// met:
53ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
63ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Redistributions of source code must retain the above copyright
73ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       notice, this list of conditions and the following disclaimer.
83ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Redistributions in binary form must reproduce the above
93ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       copyright notice, this list of conditions and the following
103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       disclaimer in the documentation and/or other materials provided
113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       with the distribution.
123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//     * Neither the name of Google Inc. nor the names of its
133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       contributors may be used to endorse or promote products derived
143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//       from this software without specific prior written permission.
153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "v8.h"
293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_IA32)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h"
333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h"
34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
35e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include "debug.h"
36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#include "stub-cache.h"
403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_)
463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass JumpPatchSite BASE_EMBEDDED {
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    info_emitted_ = false;
53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ~JumpPatchSite() {
57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(patch_site_.is_bound() == info_emitted_);
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void EmitJumpIfNotSmi(Register reg, NearLabel* target) {
61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ test(reg, Immediate(kSmiTagMask));
621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    EmitJump(not_carry, target);  // Always taken before patched.
63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void EmitJumpIfSmi(Register reg, NearLabel* target) {
66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ test(reg, Immediate(kSmiTagMask));
67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    EmitJump(carry, target);  // Never taken before patched.
68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void EmitPatchInfo() {
71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(is_int8(delta_to_patch_site));
73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ test(eax, Immediate(delta_to_patch_site));
74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    info_emitted_ = true;
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_bound() const { return patch_site_.is_bound(); }
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // jc will be patched with jz, jnc will become jnz.
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void EmitJump(Condition cc, NearLabel* target) {
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!patch_site_.is_bound() && !info_emitted_);
85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(cc == carry || cc == not_carry);
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ bind(&patch_site_);
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ j(cc, target);
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MacroAssembler* masm_;
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label patch_site_;
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool info_emitted_;
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the
1003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
1013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
1023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
1043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o edi: the JS function object being called (ie, ourselves)
1053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o esi: our context
1063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o ebp: our caller's frame pointer
1073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o esp: stack pointer (pointing to return address)
1083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
1103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-ia32.h for its layout.
111756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::Generate(CompilationInfo* info) {
1123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(info_ == NULL);
1133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  info_ = info;
1143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
1163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
117f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
118f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
120f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ int3();
121f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
122f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
123f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(ebp);  // Caller's frame pointer.
125756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ mov(ebp, esp);
126756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(esi);  // Callee's context.
127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(edi);  // Callee's JS Function.
128756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
129756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
130756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int locals_count = scope()->num_stack_slots();
131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (locals_count == 1) {
132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(Immediate(Factory::undefined_value()));
133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else if (locals_count > 1) {
134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ mov(eax, Immediate(Factory::undefined_value()));
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      for (int i = 0; i < locals_count; i++) {
136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ push(eax);
137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
1424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate local context");
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is still in edi.
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(edi);
149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      FastNewContextStub stub(heap_slots);
151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
152756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallRuntime(Runtime::kNewContext, 1);
154756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
155756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
156756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Context is returned in both eax and esi.  It replaces the context
157756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // passed to us.  It's saved in the stack and kept live in esi.
158756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
159756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
160756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy parameters into context if necessary.
161756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int num_parameters = scope()->num_parameters();
162756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
1630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      Slot* slot = scope()->parameter(i)->AsSlot();
164756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      if (slot != NULL && slot->type() == Slot::CONTEXT) {
165756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
166756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
167756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
168756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(eax, Operand(ebp, parameter_offset));
169756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
170756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int context_offset = Context::SlotOffset(slot->index());
171756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(Operand(esi, context_offset), eax);
172756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Update the write barrier. This clobbers all involved
173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // registers, so we have use a third register to avoid
174756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // clobbering esi.
175756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(ecx, esi);
176756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ RecordWrite(ecx, context_offset, eax, ebx);
177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
179756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Variable* arguments = scope()->arguments();
182756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
183756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function uses arguments object.
184756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (function_in_register) {
186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(edi);
187756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Receiver is just before the parameters on the caller's stack.
191756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int offset = scope()->num_parameters() * kPointerSize;
192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ lea(edx,
193756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(edx);
195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(Immediate(Smi::FromInt(scope()->num_parameters())));
196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Arguments to ArgumentsAccessStub:
197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
198756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiver and parameter count if the previous
199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
200756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
201756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(ecx, eax);  // Duplicate result.
2030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Move(arguments->AsSlot(), eax, ebx, edx);
2040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Move(dot_arguments_slot, ecx, ebx, edx);
206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace) {
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter, 0);
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Visit the declarations and body unless there is an illegal
2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // redeclaration.
2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (scope()->HasIllegalRedeclaration()) {
2151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Comment cmnt(masm_, "[ Declarations");
2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    scope()->VisitIllegalRedeclaration(this);
2171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
2191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    { Comment cmnt(masm_, "[ Declarations");
2201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // For named function expressions, declare the function name as a
2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // constant.
2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (scope()->is_function_scope() && scope()->function() != NULL) {
2231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        EmitDeclaration(scope()->function(), Variable::CONST, NULL);
2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      VisitDeclarations(scope()->declarations());
2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
2273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    { Comment cmnt(masm_, "[ Stack check");
2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      PrepareForBailout(info->function(), NO_REGISTERS);
2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      NearLabel ok;
2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ExternalReference stack_limit =
2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          ExternalReference::address_of_stack_limit();
2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cmp(esp, Operand::StaticVariable(stack_limit));
2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ j(above_equal, &ok, taken);
2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      StackCheckStub stub;
2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ CallStub(&stub);
2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&ok);
2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    { Comment cmnt(masm_, "[ Body");
2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ASSERT(loop_depth() == 0);
2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      VisitStatements(function()->body());
2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ASSERT(loop_depth() == 0);
2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
2453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Always emit a 'return undefined' in case control fell off the end of
2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the body.
2493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
2503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(eax, Factory::undefined_value());
2517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
256db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() {
257db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  __ Set(eax, Immediate(Smi::FromInt(0)));
258db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch}
259db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
260db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Comment cmnt(masm_, "[ Stack check");
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  NearLabel ok;
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ExternalReference stack_limit = ExternalReference::address_of_stack_limit();
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ cmp(esp, Operand::StaticVariable(stack_limit));
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(above_equal, &ok, taken);
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StackCheckStub stub;
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
269086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of this PC offset to the OSR id.  This is used to find
270086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the AST id from the unoptimized code in order to use it as a key into
271086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the deoptimization input data found in the optimized code.
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordStackCheck(stmt->OsrEntryId());
273086aeeaae12517475c22695a200be45495516549Ben Murdoch
274086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Loop stack checks can be patched to perform on-stack replacement. In
275086aeeaae12517475c22695a200be45495516549Ben Murdoch  // order to decide whether or not to perform OSR we embed the loop depth
276086aeeaae12517475c22695a200be45495516549Ben Murdoch  // in a test instruction after the call so we can extract it from the OSR
277086aeeaae12517475c22695a200be45495516549Ben Murdoch  // builtin.
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(loop_depth() > 0);
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ test(eax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker)));
280086aeeaae12517475c22695a200be45495516549Ben Murdoch
281086aeeaae12517475c22695a200be45495516549Ben Murdoch  __ bind(&ok);
282086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
283086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
284086aeeaae12517475c22695a200be45495516549Ben Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
285086aeeaae12517475c22695a200be45495516549Ben Murdoch  // we want it to work if it is.
286086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Common return label
296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
2973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
2983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(eax);
2993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
3003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(function()->end_position() - 1);
3073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
3083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
3093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
3103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(esp, ebp);
3113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(ebp);
3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize;
3141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret(arguments_bytes, ecx);
315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
3161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check that the size of the code used for returning is large enough
3171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // for the debugger's requirements.
3181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(Assembler::kJSReturnSequenceLength <=
3191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3250d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
3260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3290d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
3300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
3310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), slot_operand);
3320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3350d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
3360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
3370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Memory operands can be pushed directly.
3380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(slot_operand);
339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3420d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Slot* slot) const {
3430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
3440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->Move(result_register(), slot);
345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
3460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
3470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3500d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
3510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
3560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
3570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
3580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3610d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
3620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
3630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3670d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
3680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
3690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3720d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
3730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3760d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
3770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
3789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Set(result_register(), Immediate(lit));
3790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3820d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
3830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Immediates can be pushed directly.
3840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(lit));
3850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
3860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3880d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
3930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
3940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ jmp(false_label_);
3960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ jmp(true_label_);
3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
3990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
4010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
4030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
4050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
4070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
4090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
4100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
4110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
4120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(result_register(), lit);
4130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(true_label_, false_label_, fall_through_);
414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
4190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
4220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
4290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
4350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
4360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
4380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(Operand(esp, 0), reg);
439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
4450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
4470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4530d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
4540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(materialize_true == materialize_false);
4560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
4570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4600d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
4630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Factory::true_value());
4660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
4670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
4680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), Factory::false_value());
4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4730d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
4770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(Factory::true_value()));
4790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(&done);
4800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
4810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(Factory::false_value()));
4820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
4830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4860d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_true == true_label_);
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(materialize_false == false_label_);
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
4980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Handle<Object> value =
4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Factory::true_value() : Factory::false_value();
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), value);
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Handle<Object> value =
5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      flag ? Factory::true_value() : Factory::false_value();
5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(value));
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ jmp(true_label_);
5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ jmp(false_label_);
520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
52480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::DoTest(Label* if_true,
52580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
52680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the inlined tests assumed by the stub.
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::undefined_value());
529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::true_value());
531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_true);
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(result_register(), Factory::false_value());
533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, if_false);
534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(result_register(), Operand(result_register()));
536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(zero, if_false);
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(result_register(), Immediate(kSmiTagMask));
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(zero, if_true);
539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call the ToBoolean stub for all other cases.
541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ToBooleanStub stub;
542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CallStub(&stub);
544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(eax, Operand(eax));
545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
54680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The stub returns nonzero for true.
54780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
54880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
55180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc,
55280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
55380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
55480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
55580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
55680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
55780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
55880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(NegateCondition(cc), if_false);
55980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
56080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
56180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(if_false);
562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
566d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (slot->type()) {
568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::PARAMETER:
569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOCAL:
570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      return Operand(ebp, SlotOffset(slot));
571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::CONTEXT: {
572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      int context_chain_length =
5733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu          scope()->ContextChainLength(slot->var()->scope());
574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ LoadContext(scratch, context_chain_length);
57559151504615d929945dc59db37bf1166937748c6Steve Block      return ContextOperand(scratch, slot->index());
576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Slot::LOOKUP:
578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNREACHABLE();
579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  UNREACHABLE();
581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return Operand(eax, 0);
582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) {
586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(source, destination);
587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(destination, location);
588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
591d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst,
592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register src,
593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch1,
594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                             Register scratch2) {
595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(dst->type() != Slot::LOOKUP);  // Not yet implemented.
596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!scratch1.is(src) && !scratch2.is(src));
597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  MemOperand location = EmitSlotSearch(dst, scratch1);
598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(location, src);
599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (dst->type() == Slot::CONTEXT) {
6011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = Context::SlotOffset(dst->index());
6021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(!scratch1.is(esi) && !src.is(esi) && !scratch2.is(esi));
603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(scratch1, offset, src, scratch2);
604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     bool should_normalize,
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_true,
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_false) {
612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only prepare for bailouts before splits if we're in a test
613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // context. Otherwise, we let the Visit function deal with the
614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // preparation to avoid preparing with the same AST id twice.
615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!context()->IsTest() || !info_->IsOptimizable()) return;
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  NearLabel skip;
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) __ jmp(&skip);
619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ForwardBailoutStack* current = forward_bailout_stack_;
621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(current->expr(), state);
623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->parent();
624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) {
627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ cmp(eax, Factory::true_value());
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Split(equal, if_true, if_false, NULL);
629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ bind(&skip);
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable,
635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        Variable::Mode mode,
636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        FunctionLiteral* function) {
637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Declaration");
638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(variable != NULL);  // Must have been resolved.
6390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Slot* slot = variable->AsSlot();
640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = variable->AsProperty();
641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (slot != NULL) {
643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOCAL:
646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(Operand(ebp, SlotOffset(slot)),
648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                 Immediate(Factory::the_hole_value()));
649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
6500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(function);
651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(Operand(ebp, SlotOffset(slot)), result_register());
652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT:
656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // We bypass the general EmitSlotSearch because we know more about
657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // this specific context.
658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // The variable in the decl always resides in the current function
6601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // context.
661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (FLAG_debug_code) {
6631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          // Check that we're not inside a 'with'.
66459151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX));
665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ cmp(ebx, Operand(esi));
666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ Check(equal, "Unexpected declaration in current context.");
667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
66959151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(ContextOperand(esi, slot->index()),
670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 Immediate(Factory::the_hole_value()));
671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // No write barrier since the hole value is in old space.
672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
6730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForAccumulatorValue(function);
67459151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(ContextOperand(esi, slot->index()), result_register());
675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          int offset = Context::SlotOffset(slot->index());
6764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ mov(ebx, esi);
6774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke          __ RecordWrite(ebx, offset, result_register(), ecx);
678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP: {
682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(esi);
683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(Immediate(variable->name()));
684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Declaration nodes are always introduced in one of two modes.
685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ASSERT(mode == Variable::VAR || mode == Variable::CONST);
686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(Immediate(Smi::FromInt(attr)));
688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Push initial value, if any.
689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // Note: For variables we must not push an initial value (such as
690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // 'undefined') because we may have a (legal) redeclaration and we
691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        // must not destroy the current value.
692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (mode == Variable::CONST) {
693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ push(Immediate(Factory::the_hole_value()));
694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else if (function != NULL) {
6950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(function);
696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ push(Immediate(Smi::FromInt(0)));  // No initial value!
698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDeclareContextSlot, 4);
700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (prop != NULL) {
705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (function != NULL || mode == Variable::CONST) {
706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // We are declaring a function or constant that rewrites to a
7071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // property.  Use (keyed) IC to set the initial value.  We cannot
7081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // visit the rewrite because it's shared and we risk recording
7091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // duplicate AST IDs for bailouts from optimized code.
7101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ASSERT(prop->obj()->AsVariableProxy() != NULL);
7111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      { AccumulatorValueContext for_object(this);
7121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
7131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
7141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if (function != NULL) {
7161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ push(eax);
7170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(function);
7181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ pop(edx);
719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
7201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(edx, eax);
7211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(eax, Factory::the_hole_value());
722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
7231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ASSERT(prop->key()->AsLiteral() != NULL &&
7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             prop->key()->AsLiteral()->handle()->IsSmi());
7251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<Code> ic(Builtins::builtin(is_strict()
728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          ? Builtins::KeyedStoreIC_Initialize_Strict
729e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          : Builtins::KeyedStoreIC_Initialize));
7300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
7323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
7333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) {
737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
7423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
7433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(esi);  // The context is the first argument.
7443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(pairs));
7453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(strict_mode_flag())));
747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallRuntime(Runtime::kDeclareGlobals, 4);
7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
7493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
7580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
7681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    clause->body_target()->entry_label()->Unuse();
7691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
7810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
78380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(edx, Operand(esp, 0));  // Switch value.
7850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JumpPatchSite patch_site(masm_);
7870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
7880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      NearLabel slow_case;
78980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ mov(ecx, edx);
79080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ or_(ecx, Operand(eax));
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      patch_site.EmitJumpIfNotSmi(ecx, &slow_case);
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
79380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(edx, Operand(eax));
79480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_equal, &next_test);
79580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
79680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(clause->body_target()->entry_label());
79780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&slow_case);
79880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Record position before stub call for type feedback.
801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(clause->position());
802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    EmitCallIC(ic, &patch_site);
804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ test(eax, Operand(eax));
805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(clause->body_target()->entry_label());
808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(nested_statement.break_target());
816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ jmp(default_clause->body_target()->entry_label());
818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(clause->body_target()->entry_label());
825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(nested_statement.break_target());
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
8440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::undefined_value());
846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::null_value());
848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
8510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel convert, done_convert;
852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &convert);
854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, &done_convert);
856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
8613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
86259151504615d929945dc59db37bf1166937748c6Steve Block  // Check cache validity in generated code. This is a fast case for
86359151504615d929945dc59db37bf1166937748c6Steve Block  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
86459151504615d929945dc59db37bf1166937748c6Steve Block  // guarantee cache validity, call the runtime system to check cache
86559151504615d929945dc59db37bf1166937748c6Steve Block  // validity or get the property names in a fixed array.
86659151504615d929945dc59db37bf1166937748c6Steve Block  Label next, call_runtime;
86759151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(ecx, eax);
86859151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&next);
86959151504615d929945dc59db37bf1166937748c6Steve Block
87059151504615d929945dc59db37bf1166937748c6Steve Block  // Check that there are no elements.  Register ecx contains the
87159151504615d929945dc59db37bf1166937748c6Steve Block  // current JS object we've reached through the prototype chain.
87259151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(FieldOperand(ecx, JSObject::kElementsOffset),
87359151504615d929945dc59db37bf1166937748c6Steve Block         Factory::empty_fixed_array());
87459151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, &call_runtime);
87559151504615d929945dc59db37bf1166937748c6Steve Block
87659151504615d929945dc59db37bf1166937748c6Steve Block  // Check that instance descriptors are not empty so that we can
87759151504615d929945dc59db37bf1166937748c6Steve Block  // check for an enum cache.  Leave the map in ebx for the subsequent
87859151504615d929945dc59db37bf1166937748c6Steve Block  // prototype load.
87959151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
88059151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset));
88159151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(edx, Factory::empty_descriptor_array());
88259151504615d929945dc59db37bf1166937748c6Steve Block  __ j(equal, &call_runtime);
88359151504615d929945dc59db37bf1166937748c6Steve Block
884e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check that there is an enum cache in the non-empty instance
88559151504615d929945dc59db37bf1166937748c6Steve Block  // descriptors (edx).  This is the case if the next enumeration
88659151504615d929945dc59db37bf1166937748c6Steve Block  // index field does not contain a smi.
88759151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
88859151504615d929945dc59db37bf1166937748c6Steve Block  __ test(edx, Immediate(kSmiTagMask));
88959151504615d929945dc59db37bf1166937748c6Steve Block  __ j(zero, &call_runtime);
89059151504615d929945dc59db37bf1166937748c6Steve Block
89159151504615d929945dc59db37bf1166937748c6Steve Block  // For all objects but the receiver, check that the cache is empty.
8920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel check_prototype;
89359151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(ecx, Operand(eax));
89459151504615d929945dc59db37bf1166937748c6Steve Block  __ j(equal, &check_prototype);
89559151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
89659151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(edx, Factory::empty_fixed_array());
89759151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, &call_runtime);
89859151504615d929945dc59db37bf1166937748c6Steve Block
89959151504615d929945dc59db37bf1166937748c6Steve Block  // Load the prototype from the map and loop if non-null.
90059151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&check_prototype);
90159151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
90259151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(ecx, Factory::null_value());
90359151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, &next);
90459151504615d929945dc59db37bf1166937748c6Steve Block
90559151504615d929945dc59db37bf1166937748c6Steve Block  // The enum cache is valid.  Load the map of the object being
90659151504615d929945dc59db37bf1166937748c6Steve Block  // iterated over and use the cache for the iteration.
9070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel use_cache;
90859151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
90959151504615d929945dc59db37bf1166937748c6Steve Block  __ jmp(&use_cache);
910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
91259151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&call_runtime);
913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Duplicate the enumerable object on the stack.
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If we got a map from the runtime call, we can do a fast
917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // modification check. Otherwise, we got a fixed array, and we have
918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // to do a slow check.
9190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel fixed_array;
920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map());
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &fixed_array);
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register eax. Get the enumeration cache from it.
92459151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&use_cache);
925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset));
926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Setup the four remaining stack slots.
930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Map.
931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(edx);  // Enumeration cache.
932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Enumeration cache length (as smi).
934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register eax. Iterate through that.
938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Map (0) - force slow check.
940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Fixed array length (as smi).
943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(esp, 0 * kPointerSize));  // Get the current index.
948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Operand(esp, 1 * kPointerSize));  // Compare to the array length.
949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(above_equal, loop_statement.break_target());
950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register ebx.
952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(esp, 2 * kPointerSize));
953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the expected map from the stack or a zero map in the
956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register edx.
957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, Operand(esp, 3 * kPointerSize));
958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If not, we have to filter the key.
9610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel update_each;
962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, Operand(esp, 4 * kPointerSize));
963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &update_each);
965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the entry to a string or null if it isn't a property
967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // anymore. If the property has been removed while iterating, we
968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(ecx);  // Enumerable.
970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(ebx);  // Current entry.
971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
972756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ test(eax, Operand(eax));
973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, loop_statement.continue_target());
974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(eax));
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register ebx.
978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(result_register(), ebx);
980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { EffectContext context(this);
982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    EmitAssignment(stmt->each(), stmt->AssignmentId());
983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.continue_target());
991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EmitStackCheck(stmt);
994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&loop);
995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(loop_statement.break_target());
998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(Operand(esp), Immediate(5 * kPointerSize));
999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
10078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                       bool pretenure) {
1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // space for nested functions that don't need literals cloning. If
1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // we're running with the --always-opt or the --prepare-always-opt
1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // flag, we need to use the runtime function so that the new function
1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // we are creating here gets a chance to have its code optimized and
1013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // doesn't just get a copy of the existing unoptimized code.
1014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_always_opt &&
1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      !FLAG_prepare_always_opt &&
1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      scope()->is_function_scope() &&
10178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      info->num_literals() == 0 &&
10188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      !pretenure) {
1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    FastNewClosureStub stub;
1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(info));
1021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(esi);
1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(info));
10258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(Immediate(pretenure
10268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                      ? Factory::true_value()
10278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                      : Factory::false_value()));
10288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CallRuntime(Runtime::kNewClosure, 3);
1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
10300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
10313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
10323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
10353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
10360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitVariableLoad(expr->var());
1037e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
104059151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
104159151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
104259151504615d929945dc59db37bf1166937748c6Steve Block    TypeofState typeof_state,
104359151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow) {
104459151504615d929945dc59db37bf1166937748c6Steve Block  Register context = esi;
104559151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = edx;
104659151504615d929945dc59db37bf1166937748c6Steve Block
104759151504615d929945dc59db37bf1166937748c6Steve Block  Scope* s = scope();
104859151504615d929945dc59db37bf1166937748c6Steve Block  while (s != NULL) {
104959151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
105059151504615d929945dc59db37bf1166937748c6Steve Block      if (s->calls_eval()) {
105159151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
105259151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
105359151504615d929945dc59db37bf1166937748c6Steve Block               Immediate(0));
105459151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
105559151504615d929945dc59db37bf1166937748c6Steve Block      }
105659151504615d929945dc59db37bf1166937748c6Steve Block      // Load next context in chain.
105759151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
105859151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
105959151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering esi.
106059151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
106159151504615d929945dc59db37bf1166937748c6Steve Block    }
106259151504615d929945dc59db37bf1166937748c6Steve Block    // If no outer scope calls eval, we do not need to check more
106359151504615d929945dc59db37bf1166937748c6Steve Block    // context extensions.  If we have reached an eval scope, we check
106459151504615d929945dc59db37bf1166937748c6Steve Block    // all extensions from this point.
106559151504615d929945dc59db37bf1166937748c6Steve Block    if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
106659151504615d929945dc59db37bf1166937748c6Steve Block    s = s->outer_scope();
106759151504615d929945dc59db37bf1166937748c6Steve Block  }
106859151504615d929945dc59db37bf1166937748c6Steve Block
106959151504615d929945dc59db37bf1166937748c6Steve Block  if (s != NULL && s->is_eval_scope()) {
107059151504615d929945dc59db37bf1166937748c6Steve Block    // Loop up the context chain.  There is no frame effect so it is
107159151504615d929945dc59db37bf1166937748c6Steve Block    // safe to use raw labels here.
10720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    NearLabel next, fast;
107359151504615d929945dc59db37bf1166937748c6Steve Block    if (!context.is(temp)) {
107459151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, context);
107559151504615d929945dc59db37bf1166937748c6Steve Block    }
107659151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&next);
107759151504615d929945dc59db37bf1166937748c6Steve Block    // Terminate at global context.
107859151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(FieldOperand(temp, HeapObject::kMapOffset),
107959151504615d929945dc59db37bf1166937748c6Steve Block           Immediate(Factory::global_context_map()));
108059151504615d929945dc59db37bf1166937748c6Steve Block    __ j(equal, &fast);
108159151504615d929945dc59db37bf1166937748c6Steve Block    // Check that extension is NULL.
108259151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
108359151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, slow);
108459151504615d929945dc59db37bf1166937748c6Steve Block    // Load next context in chain.
108559151504615d929945dc59db37bf1166937748c6Steve Block    __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX));
108659151504615d929945dc59db37bf1166937748c6Steve Block    __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
108759151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(&next);
108859151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&fast);
108959151504615d929945dc59db37bf1166937748c6Steve Block  }
109059151504615d929945dc59db37bf1166937748c6Steve Block
109159151504615d929945dc59db37bf1166937748c6Steve Block  // All extension objects were empty and it is safe to use a global
109259151504615d929945dc59db37bf1166937748c6Steve Block  // load IC call.
10938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(eax, GlobalObjectOperand());
109459151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(ecx, slot->var()->name());
109559151504615d929945dc59db37bf1166937748c6Steve Block  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
109659151504615d929945dc59db37bf1166937748c6Steve Block  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
109759151504615d929945dc59db37bf1166937748c6Steve Block      ? RelocInfo::CODE_TARGET
109859151504615d929945dc59db37bf1166937748c6Steve Block      : RelocInfo::CODE_TARGET_CONTEXT;
10990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
110059151504615d929945dc59db37bf1166937748c6Steve Block}
110159151504615d929945dc59db37bf1166937748c6Steve Block
110259151504615d929945dc59db37bf1166937748c6Steve Block
110359151504615d929945dc59db37bf1166937748c6Steve BlockMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
110459151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
110559151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow) {
110659151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(slot->type() == Slot::CONTEXT);
110759151504615d929945dc59db37bf1166937748c6Steve Block  Register context = esi;
110859151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = ebx;
110959151504615d929945dc59db37bf1166937748c6Steve Block
111059151504615d929945dc59db37bf1166937748c6Steve Block  for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
111159151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
111259151504615d929945dc59db37bf1166937748c6Steve Block      if (s->calls_eval()) {
111359151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
111459151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
111559151504615d929945dc59db37bf1166937748c6Steve Block               Immediate(0));
111659151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
111759151504615d929945dc59db37bf1166937748c6Steve Block      }
111859151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
111959151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
112059151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering esi.
112159151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
112259151504615d929945dc59db37bf1166937748c6Steve Block    }
112359151504615d929945dc59db37bf1166937748c6Steve Block  }
112459151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
112559151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
112659151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, slow);
11271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // This function is used only for loads, not stores, so it's safe to
11291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // return an esi-based operand (the write barrier cannot be allowed to
11301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // destroy the esi register).
11311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return ContextOperand(context, slot->index());
113259151504615d929945dc59db37bf1166937748c6Steve Block}
113359151504615d929945dc59db37bf1166937748c6Steve Block
113459151504615d929945dc59db37bf1166937748c6Steve Block
113559151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
113659151504615d929945dc59db37bf1166937748c6Steve Block    Slot* slot,
113759151504615d929945dc59db37bf1166937748c6Steve Block    TypeofState typeof_state,
113859151504615d929945dc59db37bf1166937748c6Steve Block    Label* slow,
113959151504615d929945dc59db37bf1166937748c6Steve Block    Label* done) {
114059151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
114159151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
114259151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
114359151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
114459151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
114559151504615d929945dc59db37bf1166937748c6Steve Block  if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
114659151504615d929945dc59db37bf1166937748c6Steve Block    EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
114759151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
114859151504615d929945dc59db37bf1166937748c6Steve Block  } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
11490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
115059151504615d929945dc59db37bf1166937748c6Steve Block    Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
115159151504615d929945dc59db37bf1166937748c6Steve Block    if (potential_slot != NULL) {
115259151504615d929945dc59db37bf1166937748c6Steve Block      // Generate fast case for locals that rewrite to slots.
115359151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(eax,
115459151504615d929945dc59db37bf1166937748c6Steve Block             ContextSlotOperandCheckExtensions(potential_slot, slow));
115559151504615d929945dc59db37bf1166937748c6Steve Block      if (potential_slot->var()->mode() == Variable::CONST) {
115659151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(eax, Factory::the_hole_value());
115759151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, done);
115859151504615d929945dc59db37bf1166937748c6Steve Block        __ mov(eax, Factory::undefined_value());
115959151504615d929945dc59db37bf1166937748c6Steve Block      }
116059151504615d929945dc59db37bf1166937748c6Steve Block      __ jmp(done);
116159151504615d929945dc59db37bf1166937748c6Steve Block    } else if (rewrite != NULL) {
116259151504615d929945dc59db37bf1166937748c6Steve Block      // Generate fast case for calls of an argument function.
116359151504615d929945dc59db37bf1166937748c6Steve Block      Property* property = rewrite->AsProperty();
116459151504615d929945dc59db37bf1166937748c6Steve Block      if (property != NULL) {
116559151504615d929945dc59db37bf1166937748c6Steve Block        VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
116659151504615d929945dc59db37bf1166937748c6Steve Block        Literal* key_literal = property->key()->AsLiteral();
116759151504615d929945dc59db37bf1166937748c6Steve Block        if (obj_proxy != NULL &&
116859151504615d929945dc59db37bf1166937748c6Steve Block            key_literal != NULL &&
116959151504615d929945dc59db37bf1166937748c6Steve Block            obj_proxy->IsArguments() &&
117059151504615d929945dc59db37bf1166937748c6Steve Block            key_literal->handle()->IsSmi()) {
117159151504615d929945dc59db37bf1166937748c6Steve Block          // Load arguments object if there are no eval-introduced
117259151504615d929945dc59db37bf1166937748c6Steve Block          // variables. Then load the argument from the arguments
117359151504615d929945dc59db37bf1166937748c6Steve Block          // object using keyed load.
117459151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(edx,
11750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
117659151504615d929945dc59db37bf1166937748c6Steve Block                                                   slow));
117759151504615d929945dc59db37bf1166937748c6Steve Block          __ mov(eax, Immediate(key_literal->handle()));
117859151504615d929945dc59db37bf1166937748c6Steve Block          Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
11790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitCallIC(ic, RelocInfo::CODE_TARGET);
118059151504615d929945dc59db37bf1166937748c6Steve Block          __ jmp(done);
118159151504615d929945dc59db37bf1166937748c6Steve Block        }
118259151504615d929945dc59db37bf1166937748c6Steve Block      }
118359151504615d929945dc59db37bf1166937748c6Steve Block    }
118459151504615d929945dc59db37bf1166937748c6Steve Block  }
118559151504615d929945dc59db37bf1166937748c6Steve Block}
118659151504615d929945dc59db37bf1166937748c6Steve Block
118759151504615d929945dc59db37bf1166937748c6Steve Block
11880d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitVariableLoad(Variable* var) {
1189d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Four cases: non-this global variables, lookup slots, all other
1190d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // types of slots, and parameters that rewrite to explicit property
1191d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // accesses on the arguments object.
11920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Slot* slot = var->AsSlot();
1193d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Property* property = var->AsProperty();
1194d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1195d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (var->is_global() && !var->is_this()) {
11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Comment cmnt(masm_, "Global variable");
11973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Use inline caching. Variable name is passed in ecx and the global
11983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // object on the stack.
11998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(eax, GlobalObjectOperand());
1200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(ecx, var->name());
12013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
12020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
12030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
1204d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1205d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
120659151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
120759151504615d929945dc59db37bf1166937748c6Steve Block
120859151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
120959151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
121059151504615d929945dc59db37bf1166937748c6Steve Block    EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
121159151504615d929945dc59db37bf1166937748c6Steve Block
121259151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
1213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Lookup slot");
1214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(esi);  // Context.
1215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(Immediate(var->name()));
1216d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
121759151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
121859151504615d929945dc59db37bf1166937748c6Steve Block
12190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
1220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1221d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (slot != NULL) {
1222d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            ? "Context slot"
1224d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                            : "Stack slot");
1225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (var->mode() == Variable::CONST) {
1226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Constants may be the hole value if they have not been initialized.
1227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Unhole them.
12280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      NearLabel done;
1229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      MemOperand slot_operand = EmitSlotSearch(slot, eax);
1230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(eax, slot_operand);
1231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ cmp(eax, Factory::the_hole_value());
1232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ j(not_equal, &done);
1233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(eax, Factory::undefined_value());
1234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ bind(&done);
12350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
1236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
12370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(slot);
1238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1239d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1241d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Comment cmnt(masm_, "Rewritten parameter");
1242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(property);
1243d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Rewritten parameter accesses are of the form "slot[literal]".
1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the object is in a slot.
1246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_var);
12480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* object_slot = object_var->AsSlot();
1249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(object_slot);
1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the object.
1252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    MemOperand object_loc = EmitSlotSearch(object_slot, eax);
1253402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(edx, object_loc);
1254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Assert that the key is a smi.
1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key_literal = property->key()->AsLiteral();
1257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_NOT_NULL(key_literal);
1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(key_literal->handle()->IsSmi());
1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the key.
1261402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(eax, Immediate(key_literal->handle()));
1262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Do a keyed property load.
1264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
12650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
12660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Drop key and object left on the stack by IC.
12680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
12693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
12703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
12713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
12723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1273d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
12750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel materialized;
12763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // edi = JS function.
1278bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // ecx = literals array.
1279bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // ebx = regexp literal.
1280bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // eax = regexp literal clone.
12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1282bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
12833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
128480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1285bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ebx, FieldOperand(ecx, literal_offset));
1286bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(ebx, Factory::undefined_value());
1287bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &materialized);
1288bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in eax.
1291bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(ecx);
12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(expr->pattern()));
12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(expr->flags()));
12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1296bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ebx, eax);
1297bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1298bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1299bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1300bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label allocated, runtime_allocate;
1301bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
1302bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&allocated);
1303bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1304bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&runtime_allocate);
1305bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(ebx);
1306bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(Immediate(Smi::FromInt(size)));
1307bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1308bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(ebx);
1309bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1310bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&allocated);
1311bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Copy the content into the newly allocated memory.
1312bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // (Unroll copy loop once for better throughput).
1313bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1314bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(edx, FieldOperand(ebx, i));
1315bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
1316bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, i), edx);
1317bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, i + kPointerSize), ecx);
1318bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1319bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if ((size % (2 * kPointerSize)) != 0) {
1320bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(edx, FieldOperand(ebx, size - kPointerSize));
1321bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, size - kPointerSize), edx);
1322bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
13230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
1324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1327d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
1329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
1331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
1332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(Immediate(expr->constant_properties()));
13336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(Immediate(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
1334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
13356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
13376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in eax.
1342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
13443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Mark all computed expressions that are bound to a key that
13453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // is shadowed by a later occurrence of the same key. For the
13463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // marked expressions, no store code is emitted.
13473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  expr->CalculateEmitStore();
13483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
1349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(eax);  // Save result on the stack
1357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
1360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
13653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForAccumulatorValue(value);
1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            __ mov(ecx, Immediate(key->handle()));
1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            __ mov(edx, Operand(esp, 0));
1369e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            Handle<Code> ic(Builtins::builtin(
1370e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                is_strict() ? Builtins::StoreIC_Initialize_Strict
1371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            : Builtins::StoreIC_Initialize));
13723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu            EmitCallIC(ic, RelocInfo::CODE_TARGET);
1373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            PrepareForBailoutForId(key->id(), NO_REGISTERS);
1374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
1375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForEffect(value);
13763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(esp, 0));  // Duplicate receiver.
13820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
13830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
13843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
1385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(Smi::FromInt(NONE)));  // PropertyAttributes
1386e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kSetProperty, 4);
13873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
13883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ Drop(3);
13893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::SETTER:
1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::GETTER:
1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(esp, 0));  // Duplicate receiver.
13940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
1395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
1396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Smi::FromInt(1) :
1397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Smi::FromInt(0)));
13980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
1399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        __ CallRuntime(Runtime::kDefineAccessor, 4);
1400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      default: UNREACHABLE();
1402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
14060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
14080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
14093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
14143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
1418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
14193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
14213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
1422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(Immediate(expr->constant_elements()));
1423756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
1424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(expr->depth() == 1);
1425756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1426756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
1427756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
1428756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
1429756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (expr->depth() > 1) {
1430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1431756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1434756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
1435756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
1436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
14373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
14403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
14423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
14443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
14453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
14463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
14473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
14483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
14493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
14503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
14513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
14533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(eax);
14543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
14553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
14560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
14573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Store the subexpression value in the array's elements.
14593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ebx, Operand(esp, 0));  // Copy of array literal.
14603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
14613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(FieldOperand(ebx, offset), result_register());
14633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Update the write barrier for the array store.
1465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ RecordWrite(ebx, offset, result_register(), ecx);
1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
14683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
14710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
14730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
14743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
14753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
14763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
14773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->target());
1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1487402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
1488402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1489402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1490402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
149180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
149280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
149380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
149480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
149580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1496402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1497402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1498402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1500402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1501402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1502402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
15060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->obj());
1507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1508402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
15090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1510402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case KEYED_PROPERTY: {
1513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (property->is_arguments_access()) {
1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1516086aeeaae12517475c22695a200be45495516549Ben Murdoch          MemOperand slot_operand =
1517086aeeaae12517475c22695a200be45495516549Ben Murdoch              EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1518086aeeaae12517475c22695a200be45495516549Ben Murdoch          __ push(slot_operand);
1519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          __ mov(eax, Immediate(property->key()->AsLiteral()->handle()));
1520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          VisitForStackValue(property->obj());
1522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          VisitForAccumulatorValue(property->key());
1523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ mov(edx, Operand(esp, 0));
1525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(eax);
1526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
1527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (property->is_arguments_access()) {
1528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1529086aeeaae12517475c22695a200be45495516549Ben Murdoch          MemOperand slot_operand =
1530086aeeaae12517475c22695a200be45495516549Ben Murdoch              EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1531086aeeaae12517475c22695a200be45495516549Ben Murdoch          __ push(slot_operand);
1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          __ push(Immediate(property->key()->AsLiteral()->handle()));
1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          VisitForStackValue(property->obj());
1535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          VisitForStackValue(property->key());
1536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
1537402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1538402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1540402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1541402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
15430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    { AccumulatorValueContext context(this);
15440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
15450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
15460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableLoad(expr->target()->AsVariableProxy()->var());
15470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
15480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
15490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
15500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
15510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
15520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
15530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
15540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1556402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // For property compound assignments we need another deoptimization
1558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // point after the property load.
1559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (property != NULL) {
1560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
156380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
1564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(eax);  // Left operand goes on the stack.
1565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitForAccumulatorValue(expr->value());
1566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
156780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
156880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
156980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
157080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
15710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
157280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
157380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      EmitInlineSmiBinaryOp(expr,
157480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
157580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
157680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
1577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            expr->value());
157880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
15790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitBinaryOp(op, mode);
158080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Deoptimization point in case the binary operation may have side effects.
1583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr->binary_operation(), TOS_REG);
158480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
15850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1586402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1588402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1589402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1592402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1593402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1594402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
15950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->Plug(eax);
1598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1600402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1606402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1608402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1609d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(ecx, Immediate(key->handle()));
1613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
16140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1618d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
16210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
162580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
162680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
162780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              OverwriteMode mode,
162880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* left,
1629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Expression* right) {
163080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do combined smi check of the operands. Left operand is on the
163180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stack. Right operand is in eax.
1632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  NearLabel done, smi_case, stub_call;
163380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ pop(edx);
163480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(ecx, eax);
163580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ or_(eax, Operand(edx));
1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  JumpPatchSite patch_site(masm_);
1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  patch_site.EmitJumpIfSmi(eax, &smi_case);
163880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
163980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&stub_call);
1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(eax, ecx);
1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeRecordingBinaryOpStub stub(op, mode);
1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EmitCallIC(stub.GetCode(), &patch_site);
164380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&done);
164480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Smi case.
164680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
164780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(eax, edx);  // Copy left operand in case of a stub call.
164880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
164980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
165080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
165180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
165280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
165380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ sar_cl(eax);  // No checks of result necessary
165480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
165580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
165680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL: {
165780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label result_ok;
165880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
165980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
166080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ shl_cl(eax);
166180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Check that the *signed* result fits in a smi.
166280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(eax, 0xc0000000);
166380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(positive, &result_ok);
166480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(ecx);
166580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(&stub_call);
166680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&result_ok);
166780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
166880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
167080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR: {
167180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label result_ok;
167280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
167380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
167480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ shr_cl(eax);
167580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ test(eax, Immediate(0xc0000000));
167680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(zero, &result_ok);
167780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(ecx);
167880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(&stub_call);
167980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&result_ok);
168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ add(eax, Operand(ecx));
168580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
168780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ sub(eax, Operand(ecx));
168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
169180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MUL: {
169280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ imul(eax, Operand(ecx));
169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
169580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ test(eax, Operand(eax));
169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_zero, &done, taken);
169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ mov(ebx, edx);
169880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ or_(ebx, Operand(ecx));
169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(negative, &stub_call);
170080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
170180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
170280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
170380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ or_(eax, Operand(ecx));
170480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
170580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
170680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ and_(eax, Operand(ecx));
170780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
170880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
170980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ xor_(eax, Operand(ecx));
171080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
171180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
171280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
171380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
171480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
171580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
17160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
171780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
171880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
171980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
172080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitBinaryOp(Token::Value op,
172180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ pop(edx);
1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeRecordingBinaryOpStub stub(op, mode);
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EmitCallIC(stub.GetCode(), NULL);  // NULL signals no inlined smi code.
17250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
1733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr);
1734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
1738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
17510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
17520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
1753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(eax);  // Preserve value.
17570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
1758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(edx, eax);
1759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(eax);  // Restore value.
1760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(ecx, prop->key()->AsLiteral()->handle());
1761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<Code> ic(Builtins::builtin(
1762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          is_strict() ? Builtins::StoreIC_Initialize_Strict
1763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      : Builtins::StoreIC_Initialize));
17640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
1765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(eax);  // Preserve value.
1769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (prop->is_synthetic()) {
1770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        ASSERT(prop->obj()->AsVariableProxy() != NULL);
1771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        ASSERT(prop->key()->AsLiteral() != NULL);
1772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        { AccumulatorValueContext for_object(this);
1773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
1775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ mov(edx, eax);
1776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
1777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
1778e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForStackValue(prop->obj());
1779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForAccumulatorValue(prop->key());
1780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ mov(ecx, eax);
1781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ pop(edx);
1782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
1783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(eax);  // Restore value.
1784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<Code> ic(Builtins::builtin(
1785e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
1786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      : Builtins::KeyedStoreIC_Initialize));
17870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
1788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(eax);
1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1796d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
17970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               Token::Value op) {
1798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand sides that rewrite to explicit property accesses do not reach
1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // here.
18003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(var != NULL);
18010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(var->is_global() || var->AsSlot() != NULL);
1802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
18033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (var->is_global()) {
1804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!var->is_this());
1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Assignment to a global variable.  Use inline caching for the
1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // assignment.  Right-hand-side value is passed in eax, variable name in
1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // ecx, and the global object on the stack.
18083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ecx, var->name());
18098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(edx, GlobalObjectOperand());
18101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Handle<Code> ic(Builtins::builtin(
18111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        is_strict() ? Builtins::StoreIC_Initialize_Strict
18121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                    : Builtins::StoreIC_Initialize));
18131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
18151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (op == Token::INIT_CONST) {
18161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Like var declarations, const declarations are hoisted to function
18171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // scope.  However, unlike var initializers, const initializers are able
18181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // to drill a hole to that function context, even from inside a 'with'
18191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // context.  We thus bypass the normal static scope lookup.
18201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Slot* slot = var->AsSlot();
18211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label skip;
18221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    switch (slot->type()) {
18231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case Slot::PARAMETER:
18241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // No const parameters.
18251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        UNREACHABLE();
18261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        break;
18271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case Slot::LOCAL:
18281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(edx, Operand(ebp, SlotOffset(slot)));
18291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ cmp(edx, Factory::the_hole_value());
18301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ j(not_equal, &skip);
18311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(Operand(ebp, SlotOffset(slot)), eax);
18321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        break;
18331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case Slot::CONTEXT: {
18341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(ecx, ContextOperand(esi, Context::FCONTEXT_INDEX));
18351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(edx, ContextOperand(ecx, slot->index()));
18361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ cmp(edx, Factory::the_hole_value());
18371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ j(not_equal, &skip);
18381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(ContextOperand(ecx, slot->index()), eax);
18391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        int offset = Context::SlotOffset(slot->index());
18401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(edx, eax);  // Preserve the stored value in eax.
18411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ RecordWrite(ecx, offset, edx, ebx);
18421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        break;
18431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
18441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case Slot::LOOKUP:
18451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ push(eax);
18461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ push(esi);
18471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ push(Immediate(var->name()));
18481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
18491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        break;
18501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
18511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&skip);
18521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (var->mode() != Variable::CONST) {
18541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Perform the assignment for non-const variables.  Const assignments
18551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // are simply skipped.
18560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = var->AsSlot();
1857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (slot->type()) {
1858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case Slot::PARAMETER:
1859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case Slot::LOCAL:
1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment.
1861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(Operand(ebp, SlotOffset(slot)), eax);
1862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::CONTEXT: {
1865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        MemOperand target = EmitSlotSearch(slot, ecx);
1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment and issue the write barrier.
1867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(target, eax);
1868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The value of the assignment is in eax.  RecordWrite clobbers its
1869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // register arguments.
1870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(edx, eax);
18711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        int offset = Context::SlotOffset(slot->index());
1872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ RecordWrite(ecx, offset, edx, ebx);
1873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
18743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
1875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case Slot::LOOKUP:
18771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // Call the runtime for the assignment.
1878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(eax);  // Value.
1879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(esi);  // Context.
1880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ push(Immediate(var->name()));
1881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ push(Immediate(Smi::FromInt(strict_mode_flag())));
1882e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ CallRuntime(Runtime::kStoreContextSlot, 4);
1883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
18843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
18853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
18863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
18873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
18883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
1891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
1893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
18943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1899e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1900e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(esp, kPointerSize));  // Receiver is now under value.
1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1906e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(ecx, prop->key()->AsLiteral()->handle());
19084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
19094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ mov(edx, Operand(esp, 0));
19104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
19114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(edx);
19124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
1913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<Code> ic(Builtins::builtin(
1914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      is_strict() ? Builtins::StoreIC_Initialize_Strict
1915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                  : Builtins::StoreIC_Initialize));
19160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
1920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(eax);  // Result of assignment, saved even if not needed.
1921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(esp, kPointerSize));  // Receiver is under value.
1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(eax);
1924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ Drop(1);
1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(eax);
1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1931d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
1933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
1935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
1938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
1939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
1940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(esp, 2 * kPointerSize));
1941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
1942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
1943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
19456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(ecx);
19466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (expr->ends_initialization_block()) {
19476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(edx, Operand(esp, 0));  // Leave receiver on the stack for later.
19486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
19496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(edx);
19506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
1952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
1953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<Code> ic(Builtins::builtin(
1954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
1955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                  : Builtins::KeyedStoreIC_Initialize));
19560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, RelocInfo::CODE_TARGET);
1957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
1959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
19606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(edx);
1961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(eax);  // Result of assignment, saved even if not needed.
19626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ push(edx);
1963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
1964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(eax);
1965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
19680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
1969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1970d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1971d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1972d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
1973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
1974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
1975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->obj());
1978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
1979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(eax);
1980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
19810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
19820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
1983402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(edx);
1984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
1985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(eax);
1986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
1991e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       Handle<Object> name,
1992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
1993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
1994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
19953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
1996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
19973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
19983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
19993e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
20003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    __ Set(ecx, Immediate(name));
20013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source position of the IC call.
2003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
2004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
20058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
20060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
2007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
2008d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
2009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
20100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2012d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
20147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
20157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Expression* key,
20167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            RelocInfo::Mode mode) {
20178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
20188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
20198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Swap the name of the function and the receiver on the stack to follow
20218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the calling convention for call ICs.
20228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(ecx);
20238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(eax);
20248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(ecx);
20258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the arguments.
20277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
20287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int arg_count = args->length();
2029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
20303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
20313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
20323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
20337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
20347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Record source position of the IC call.
2035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
20367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
20378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
20388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize));  // Key.
20390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  EmitCallIC(ic, mode);
2040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
20417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Restore context register.
20427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
20438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->DropAndPlug(1, eax);  // Drop the key still on the stack.
20447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
20457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
20467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2047d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) {
2048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
2049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2050d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
20523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
20533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
20543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2056d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
2057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
2060d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ CallStub(&stub);
2061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
20623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
20633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
20640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, eax);
2065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2068e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
2069e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                      int arg_count) {
2070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push copy of the first argument or undefined if it doesn't exist.
2071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (arg_count > 0) {
2072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(Operand(esp, arg_count * kPointerSize));
2073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(Immediate(Factory::undefined_value()));
2075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push the receiver of the enclosing function.
2078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
2079e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push the strict mode flag.
2081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(strict_mode_flag())));
2082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
2084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 ? Runtime::kResolvePossiblyDirectEvalNoLookup
2085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 : Runtime::kResolvePossiblyDirectEval, 4);
2086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2089d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
2091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We want to verify that RecordJSReturnSite gets called on all paths
2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // through this function.  Avoid early returns.
2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->return_is_recorded_ = false;
2094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
2095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2096d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
2097d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* fun = expr->expression();
2098d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Variable* var = fun->AsVariableProxy()->AsVariable();
2099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (var != NULL && var->is_possibly_eval()) {
2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // resolve the function we need to call and the receiver of the
2103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // call.  Then we call the resolved function using the given
2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // arguments.
2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope pos_scope(masm()->positions_recorder());
21083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(fun);
21093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Reserved receiver slot.
21103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ push(Immediate(Factory::undefined_value()));
2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the arguments.
21133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      for (int i = 0; i < arg_count; i++) {
21143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(args->at(i));
21153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // If we know that eval can only be shadowed by eval-introduced
2118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // variables we attempt to load the global eval function directly
2119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // in generated code. If we succeed, there is no need to perform a
2120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // context lookup in the runtime system.
2121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Label done;
2122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
2123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Label slow;
2124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
2125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          NOT_INSIDE_TYPEOF,
2126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          &slow);
2127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Push the function and resolve eval.
2128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ push(eax);
2129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
2130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ jmp(&done);
2131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ bind(&slow);
21323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Push copy of the function (found below the arguments) and
2135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // resolve eval.
2136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ push(Operand(esp, (arg_count + 1) * kPointerSize));
2137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
2138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (done.is_linked()) {
2139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        __ bind(&done);
2140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
21423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // The runtime call returns a pair of values in eax (function) and
21433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // edx (receiver). Touch up the stack with the right values.
21443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
21453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
21463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
2148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(expr->position());
2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
2152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    RecordJSReturnSite(expr);
2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
21550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, eax);
2156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (var != NULL && !var->is_this() && var->is_global()) {
2157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Push global object as receiver for the call IC.
21588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(GlobalObjectOperand());
2159e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
21600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (var != NULL && var->AsSlot() != NULL &&
21610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             var->AsSlot()->type() == Slot::LOOKUP) {
216259151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
216359151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
216459151504615d929945dc59db37bf1166937748c6Steve Block
2165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
21663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Generate code for loading from variables potentially shadowed
21673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // by eval-introduced variables.
21683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
21693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      NOT_INSIDE_TYPEOF,
21703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      &slow,
21713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                      &done);
21723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
217359151504615d929945dc59db37bf1166937748c6Steve Block
217459151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
217559151504615d929945dc59db37bf1166937748c6Steve Block    // Call the runtime to find the function to call (returned in eax)
217659151504615d929945dc59db37bf1166937748c6Steve Block    // and the object holding it (returned in edx).
2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(var->name()));
2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(eax);  // Function.
2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(edx);  // Receiver.
218259151504615d929945dc59db37bf1166937748c6Steve Block
218359151504615d929945dc59db37bf1166937748c6Steve Block    // If fast case code has been generated, emit code to push the
218459151504615d929945dc59db37bf1166937748c6Steve Block    // function and receiver and have the slow path jump around this
218559151504615d929945dc59db37bf1166937748c6Steve Block    // code.
218659151504615d929945dc59db37bf1166937748c6Steve Block    if (done.is_linked()) {
218759151504615d929945dc59db37bf1166937748c6Steve Block      Label call;
218859151504615d929945dc59db37bf1166937748c6Steve Block      __ jmp(&call);
218959151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&done);
219059151504615d929945dc59db37bf1166937748c6Steve Block      // Push function.
219159151504615d929945dc59db37bf1166937748c6Steve Block      __ push(eax);
219259151504615d929945dc59db37bf1166937748c6Steve Block      // Push global receiver.
21938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ mov(ebx, GlobalObjectOperand());
219459151504615d929945dc59db37bf1166937748c6Steve Block      __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
219559151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&call);
219659151504615d929945dc59db37bf1166937748c6Steve Block    }
219759151504615d929945dc59db37bf1166937748c6Steve Block
2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitCallWithStub(expr);
2199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (fun->AsProperty() != NULL) {
2200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to an object property.
2201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Property* prop = fun->AsProperty();
2202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = prop->key()->AsLiteral();
2203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (key != NULL && key->handle()->IsSymbol()) {
2204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // Call to a named property, use call IC.
2205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      { PreservePositionScope scope(masm()->positions_recorder());
2206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForStackValue(prop->obj());
2207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
22107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Call to a keyed property.
22117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // For a synthetic property use keyed load IC followed by function call,
22120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // for a regular property use keyed EmitCallIC.
2213402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (prop->is_synthetic()) {
22141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // Do not visit the object and key subexpressions (they are shared
22151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // by all occurrences of the same rewritten parameter).
22161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(prop->obj()->AsVariableProxy() != NULL);
22171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
22181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
22191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        MemOperand operand = EmitSlotSearch(slot, edx);
22201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(edx, operand);
22211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
22221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(prop->key()->AsLiteral() != NULL);
22231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
22241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ mov(eax, prop->key()->AsLiteral()->handle());
22251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
22267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // Record source code position for IC call.
2227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        SetSourcePosition(prop->position());
2228402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
22297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
22300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        EmitCallIC(ic, RelocInfo::CODE_TARGET);
2231402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // Push result (function).
2232402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(eax);
2233402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // Push Global receiver.
22348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ mov(ecx, GlobalObjectOperand());
2235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
22367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        EmitCallWithStub(expr);
2237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
22381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        { PreservePositionScope scope(masm()->positions_recorder());
22391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          VisitForStackValue(prop->obj());
22401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
22417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
2242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
22443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call to some other expression.  If the expression is an anonymous
2246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // function literal not called in a loop, mark it as one that should
2247d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // also use the full code generator.
2248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    FunctionLiteral* lit = fun->AsFunctionLiteral();
2249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (lit != NULL &&
2250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        lit->name()->Equals(Heap::empty_string()) &&
2251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        loop_depth() == 0) {
2252d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      lit->set_try_full_codegen(true);
2253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
22553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(fun);
22563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
22588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(ebx, GlobalObjectOperand());
2259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
2261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    EmitCallWithStub(expr);
22623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
2265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // RecordJSReturnSite should have been called.
2266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->return_is_recorded_);
2267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
22683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
22693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
22703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2271d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
2273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
2274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
2275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
2276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
227780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
227880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
227980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
22800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
2281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
2283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
22860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
2287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
2290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
2291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
2292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
229380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into edi and eax.
2294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ Set(eax, Immediate(arg_count));
229580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(edi, Operand(esp, arg_count * kPointerSize));
2296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
2298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
22990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
231180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
231780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
233180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask | 0x80000000));
233780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
235180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Factory::null_value());
2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_false);
2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, if_false);
2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(ecx, LAST_JS_OBJECT_TYPE);
2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
236980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(below_equal, if_true, if_false, fall_through);
2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
23753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
23763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
23773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
23793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
23813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
23823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
238380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
23840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
23850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
23863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ test(eax, Immediate(kSmiTagMask));
23883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(equal, if_false);
23893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx);
2390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
239180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(above_equal, if_true, if_false, fall_through);
23923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
23943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
23953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
23963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
240580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ebx, Immediate(1 << Map::kIsUndetectable));
2414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
241580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2421756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2422756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ZoneList<Expression*>* args) {
2423756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(args->length() == 1);
2424756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
24250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2426756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2427756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label materialize_true, materialize_false;
2428756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
2429756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
243080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2433756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(3110205): Implement this.
2435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Currently unimplemented.  Emit false, a safe choice.
2436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2437756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ jmp(if_false);
24380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2439756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2440756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2441756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
245080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, if_false);
2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
245880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
247280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_false);
2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
2479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
248080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
249480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_false);
2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
2501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
250280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
251580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(eax, StandardFrameConstants::kContextOffset),
2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &check_frame_marker);
2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset));
2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
2533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
253480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
25440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
25450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
255080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(ebx);
2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Operand(ebx));
2556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
255780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // parameter count in eax.
25680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, eax);
2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
25730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (FLAG_debug_code) __ AbortIfNotSmi(eax);
25960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &null);
2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, eax);  // Map is now in eax.
2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, &null);
2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // As long as JS_FUNCTION_TYPE is the last instance type and it is
2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // LAST_JS_OBJECT_TYPE.
2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
26208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &function);
2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the constructor in the map is a function.
2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &non_function_constructor);
2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // eax now contains the constructor function. Grab the
2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::function_class_symbol());
2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::Object_symbol());
2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::null_value());
2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING
2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
26660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(1));
26670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(2));
2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif
2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Factory::undefined_value());
26730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
2678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 0);
2679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber);
2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
26873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
26883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edi, eax);
2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ PrepareCallCFunction(0, ebx);
2694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in eax to 0.(32 random bits) in a double
2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // This is implemented on both SSE2 and FPU.
2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CpuFeatures::IsSupported(SSE2)) {
2701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope fscope(SSE2);
2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movd(xmm1, Operand(ebx));
2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movd(xmm0, Operand(eax));
2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ cvtss2sd(xmm1, xmm1);
2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ pxor(xmm0, xmm1);
2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ subsd(xmm0, xmm1);
2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x4130000000000000 is 1.0 x 2^20 as a double.
2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(0x41300000));
2713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0));
2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fsubp(1);
2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset));
2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, edi);
27210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
2728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
27290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
27310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
27330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
2738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
2740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
27410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
27430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
27440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
2745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
27460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &done);
2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
27650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
27720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MathPowStub stub;
2776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
27770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
27850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
2786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(ebx);  // eax = value. ebx = object.
2787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel done;
2789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ebx, Immediate(kSmiTagMask));
2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(zero, &done);
2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
2794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
2795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &done);
2796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
2798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
2799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
2800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
2801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, eax);
2802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx);
2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
28050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
2810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
2811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
28130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
2816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
28170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
2822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
28277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(eax, ebx);
28287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
28327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
28350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(ebx);
2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
28407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
28417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
28430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
28447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = ebx;
28467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = eax;
28477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch = ecx;
28487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = edx;
28497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
28517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
28537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
28547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
28557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
28567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
28577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      scratch,
28587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
28597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
28607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
28617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
28627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
28637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
28647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
28677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
28687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
28697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::nan_value()));
28707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
2873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Move the undefined value into the result register, which will
28747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
28757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::undefined_value()));
28767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
28777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
28797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
28807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
28820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
2883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
28877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
28887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
28900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
28917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = ebx;
28937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = eax;
28947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch1 = ecx;
28957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch2 = edx;
28967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
28977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
28987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
28997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
29017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
29027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
29037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
29047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
29057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch1,
29067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  scratch2,
29077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
29087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
29097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
29107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
29117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
29127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
29137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
29147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
29167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
29177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
29187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Factory::empty_string()));
29197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
29207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
29227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
29237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
29247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Smi::FromInt(0)));
29257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
29267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
29287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
29297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
29310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
29327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
29337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
29347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
2936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
2949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
2952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
2954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
2960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranscendentalCacheStub stub(TranscendentalCache::SIN,
2962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               TranscendentalCacheStub::TAGGED);
2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
29640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
2971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
2972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranscendentalCacheStub stub(TranscendentalCache::COS,
2973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               TranscendentalCacheStub::TAGGED);
2974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(args->length() == 1);
2975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForStackValue(args->at(0));
2976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
2977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(eax);
2978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
2982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the argument on the stack and call the stub.
2983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranscendentalCacheStub stub(TranscendentalCache::LOG,
2984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               TranscendentalCacheStub::TAGGED);
2985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
29860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
2993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
29950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
2996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
29970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
3002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
3003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int arg_count = args->length() - 2;  // For receiver and function.
30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Receiver.
3006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < arg_count; i++) {
30070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i + 1));
3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
30090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(arg_count + 1));  // Function.
3010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // InvokeFunction requires function in edi. Move it in there.
3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!result_register().is(edi)) __ mov(edi, result_register());
3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
3014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeFunction(edi, count, CALL_FUNCTION);
3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
30160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
3021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the arguments on the stack and call the stub.
3022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RegExpConstructResultStub stub;
3023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
30240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
30260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
3027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
30280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
3033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
30340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
30360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
3037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label done;
3038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label slow_case;
3039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Register object = eax;
3040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Register index_1 = ebx;
3041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Register index_2 = ecx;
3042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Register elements = edi;
3043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Register temp = edx;
3044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(object, Operand(esp, 2 * kPointerSize));
3045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fetch the map and check if array is in fast case.
3046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that object doesn't require security checks and
3047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // has no indexed interceptor.
3048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CmpObjectType(object, FIRST_JS_OBJECT_TYPE, temp);
3049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(below, &slow_case);
3050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
3051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            KeyedLoadIC::kSlowCaseBitFieldMask);
3052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(not_zero, &slow_case);
3053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check the object's elements are in fast case and writable.
3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(elements, FieldOperand(object, JSObject::kElementsOffset));
3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         Immediate(Factory::fixed_array_map()));
3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(not_equal, &slow_case);
3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that both indices are smis.
3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(index_1, Operand(esp, 1 * kPointerSize));
3062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(index_2, Operand(esp, 0));
3063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(temp, index_1);
3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ or_(temp, Operand(index_2));
3065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ test(temp, Immediate(kSmiTagMask));
3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(not_zero, &slow_case);
3067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check that both indices are valid.
3069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(temp, FieldOperand(object, JSArray::kLengthOffset));
3070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ cmp(temp, Operand(index_1));
3071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(below_equal, &slow_case);
3072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ cmp(temp, Operand(index_2));
3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(below_equal, &slow_case);
3074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Bring addresses into index1 and index2.
3076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1));
3077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2));
3078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Swap elements.  Use object and temp as scratch registers.
3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(object, Operand(index_1, 0));
3081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(temp,   Operand(index_2, 0));
3082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(Operand(index_2, 0), object);
3083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(Operand(index_1, 0), temp);
3084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label new_space;
3086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ InNewSpace(elements, temp, equal, &new_space);
3087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(object, elements);
3089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ RecordWriteHelper(object, index_1, temp);
3090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ RecordWriteHelper(elements, index_2, temp);
3091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&new_space);
3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We are done. Drop elements from the stack, and return undefined.
3094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ add(Operand(esp), Immediate(3 * kPointerSize));
3095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(eax, Factory::undefined_value());
3096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&done);
3097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&slow_case);
3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kSwapElements, 3);
3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&done);
31020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
3107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
3108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
3110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
3113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Top::global_context()->jsfunction_result_caches());
3114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
3115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
3116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(eax, Factory::undefined_value());
31170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
3118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = eax;
3124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = ebx;
3125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register tmp = ecx;
312659151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(cache, ContextOperand(esi, Context::GLOBAL_INDEX));
3127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
3128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldOperand(cache, GlobalObject::kGlobalContextOffset));
312959151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
3131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
3134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
3135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
3138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &not_found);
3139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1));
3141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
3144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(cache);
3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(key);
3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
3148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
31500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3154bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
3155bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
3156bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3157bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = eax;
3158bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = ebx;
3159bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = ecx;
3160bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
31610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
31620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3163bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
3164bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3165bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label done, fail, ok;
3166bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(left, Operand(right));
3167bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
3168bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
3169bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(tmp, left);
3170bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ and_(Operand(tmp), right);
3171bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ test(Operand(tmp), Immediate(kSmiTagMask));
3172bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(zero, &fail);
3173bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CmpObjectType(left, JS_REGEXP_TYPE, tmp);
3174bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
3175bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset));
3176bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
3177bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3178bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3179bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
3180bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
3181bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(eax, Immediate(Factory::false_value()));
3182bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&done);
3183bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
3184bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(eax, Immediate(Factory::true_value()));
3185bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
3186bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
31870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3188bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3189bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3190bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
319280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
319380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
31940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
319580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
319680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (FLAG_debug_code) {
319780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ AbortIfNotString(eax);
319880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
319980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
320080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
320180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
320280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
320380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
32040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
32050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
320680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
320780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ test(FieldOperand(eax, String::kHashFieldOffset),
320880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Immediate(String::kContainsCachedArrayIndexMask));
3209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
321080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
321180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
321380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
321480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
321580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
321680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
321780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
32180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
321980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
322080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (FLAG_debug_code) {
322180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ AbortIfNotString(eax);
322280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
322380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
322480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
322580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(eax, eax);
322680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
322880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
322980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
323080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
32318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
3232b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label bailout, done, one_char_separator, long_separator,
3233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      non_trivial_array, not_size_one_array, loop,
3234b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
32358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(args->length() == 2);
32378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We will leave the separator on the stack until the end of the function.
32388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForStackValue(args->at(1));
32398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load this to eax (= array)
32408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(args->at(0));
32418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // All aliases of the same register have disjoint lifetimes.
32428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register array = eax;
3243b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register elements = no_reg;  // Will be eax.
32448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3245b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register index = edx;
32468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3247b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register string_length = ecx;
32488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3249b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register string = esi;
32508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register scratch = ebx;
32528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3253b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register array_length = edi;
3254b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register result_pos = no_reg;  // Will be edi.
32558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3256b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Separator operand is already pushed.
3257b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Operand separator_operand = Operand(esp, 2 * kPointerSize);
3258b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Operand result_operand = Operand(esp, 1 * kPointerSize);
3259b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Operand array_length_operand = Operand(esp, 0);
3260b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ sub(Operand(esp), Immediate(2 * kPointerSize));
3261b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cld();
3262b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check that the array is a JSArray
32638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test(array, Immediate(kSmiTagMask));
32648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
32658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
32668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
32678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that the array has fast elements.
32698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
32708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang            1 << Map::kHasFastElements);
32718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
32728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3273b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // If the array has length zero, return the empty string.
3274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
3275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(array_length);
3276b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(not_zero, &non_trivial_array);
3277b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(result_operand, Factory::empty_string());
32788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ jmp(&done);
32798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3280b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Save the array length.
3281b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&non_trivial_array);
3282b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(array_length_operand, array_length);
32838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3284b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Save the FixedArray containing array's elements.
32858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // End of array's live range.
3286b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  elements = array;
3287b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(elements, FieldOperand(array, JSArray::kElementsOffset));
32888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  array = no_reg;
32898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
32908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3291b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check that all array elements are sequential ASCII strings, and
3292b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // accumulate the sum of their lengths, as a smi-encoded value.
3293b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ Set(index, Immediate(0));
3294b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ Set(string_length, Immediate(0));
3295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Loop condition: while (index < length).
3296b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live loop registers: index, array_length, string,
3297b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //                      scratch, string_length, elements.
3298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_debug_code) {
3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ cmp(index, Operand(array_length));
3300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin");
3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop);
3303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(string, FieldOperand(elements,
3304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              index,
3305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              times_pointer_size,
3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              FixedArray::kHeaderSize));
3307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ test(string, Immediate(kSmiTagMask));
33088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
3309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3310b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
33118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ and_(scratch, Immediate(
33128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
33138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
33148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
3315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ add(string_length,
3316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kLengthOffset));
3317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(overflow, &bailout);
3318b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ add(Operand(index), Immediate(1));
3319b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(index, Operand(array_length));
3320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(less, &loop);
3321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3322b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // If array_length is 1, return elements[0], a string.
3323b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(array_length, 1);
3324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(not_equal, &not_size_one_array);
3325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
3326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(result_operand, scratch);
3327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&done);
3328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3329b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&not_size_one_array);
3330b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3331b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // End of array_length live range.
3332b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  result_pos = array_length;
3333b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  array_length = no_reg;
3334b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3335b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live registers:
3336b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // string_length: Sum of string lengths, as a smi.
3337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // elements: FixedArray of strings.
3338b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3339b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check that the separator is a flat ASCII string.
3340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, separator_operand);
3341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ test(string, Immediate(kSmiTagMask));
33428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(zero, &bailout);
3343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
33458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ and_(scratch, Immediate(
33468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(scratch, ASCII_STRING_TYPE);
33488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
33498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3350b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Add (separator length times array_length) - separator length
3351b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // to string_length.
3352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, separator_operand);
3353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset));
3354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ sub(string_length, Operand(scratch));  // May be negative, temporarily.
3355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ imul(scratch, array_length_operand);
3356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(overflow, &bailout);
3357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ add(string_length, Operand(scratch));
3358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(overflow, &bailout);
3359b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3360b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
33618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Live registers and stack values:
3362b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   string_length
3363b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   elements
3364b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ AllocateAsciiString(result_pos, string_length, scratch,
3365b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                         index, string, &bailout);
3366b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(result_operand, result_pos);
3367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
3368b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3369b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3370b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, separator_operand);
3371b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(FieldOperand(string, SeqAsciiString::kLengthOffset),
3372b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         Immediate(Smi::FromInt(1)));
3373b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(equal, &one_char_separator);
3374b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(greater, &long_separator);
3375b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3376b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3377b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Empty separator case
3378b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(index, Immediate(0));
3379b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&loop_1_condition);
33808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Loop condition: while (index < length).
3381b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_1);
3382b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Each iteration of the loop concatenates one string to the result.
3383b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live values in registers:
3384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   index: which element of the elements array we are adding to the result.
3385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   result_pos: the position to which we are currently copying characters.
3386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   elements: the FixedArray of strings we are joining.
3387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Get string = array[index].
3389b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, FieldOperand(elements, index,
3390b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              times_pointer_size,
3391b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              FixedArray::kHeaderSize));
3392b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string_length,
3393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, String::kLengthOffset));
3394b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
3395b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(string,
3396b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kHeaderSize));
3397b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
3398b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ add(Operand(index), Immediate(1));
3399b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_1_condition);
3400b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(index, array_length_operand);
3401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(less, &loop_1);  // End while (index < length).
3402b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&done);
34038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
34048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // One-character separator case
3407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&one_char_separator);
3408b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Replace separator with its ascii character value.
3409b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov_b(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize));
3410b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov_b(separator_operand, scratch);
3411b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3412b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ Set(index, Immediate(0));
3413b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Jump into the loop after the code that copies the separator, so the first
3414b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // element is not preceded by a separator
3415b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&loop_2_entry);
3416b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Loop condition: while (index < length).
3417b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_2);
3418b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Each iteration of the loop concatenates one string to the result.
3419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live values in registers:
3420b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   index: which element of the elements array we are adding to the result.
3421b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   result_pos: the position to which we are currently copying characters.
3422b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3423b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Copy the separator character to the result.
3424b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov_b(scratch, separator_operand);
3425b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov_b(Operand(result_pos, 0), scratch);
3426b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ inc(result_pos);
3427b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3428b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_2_entry);
3429b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Get string = array[index].
3430b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, FieldOperand(elements, index,
3431b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              times_pointer_size,
3432b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              FixedArray::kHeaderSize));
3433b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string_length,
3434b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, String::kLengthOffset));
3435b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
3436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(string,
3437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kHeaderSize));
3438b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
3439b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ add(Operand(index), Immediate(1));
3440b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3441b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(index, array_length_operand);
3442b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(less, &loop_2);  // End while (index < length).
3443b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&done);
3444b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3446b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Long separator case (separator is more than one character).
3447b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&long_separator);
3448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ Set(index, Immediate(0));
3450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Jump into the loop after the code that copies the separator, so the first
3451b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // element is not preceded by a separator
3452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&loop_3_entry);
3453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Loop condition: while (index < length).
3454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_3);
3455b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Each iteration of the loop concatenates one string to the result.
3456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live values in registers:
3457b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   index: which element of the elements array we are adding to the result.
3458b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   result_pos: the position to which we are currently copying characters.
3459b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Copy the separator to the result.
3461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, separator_operand);
3462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string_length,
3463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, String::kLengthOffset));
3464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
3465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(string,
3466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kHeaderSize));
3467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
3468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_3_entry);
3470b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Get string = array[index].
3471b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, FieldOperand(elements, index,
3472b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              times_pointer_size,
3473b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              FixedArray::kHeaderSize));
3474b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string_length,
3475b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, String::kLengthOffset));
3476b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
3477b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(string,
3478b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kHeaderSize));
3479b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
34808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(Operand(index), Immediate(1));
3481b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3482b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(index, array_length_operand);
3483b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(less, &loop_3);  // End while (index < length).
3484b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&done);
3485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
34868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
34878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&bailout);
3488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(result_operand, Factory::undefined_value());
34898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&done);
3490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(eax, result_operand);
34918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Drop temp values from the stack, and restore context register.
3492b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ add(Operand(esp), Immediate(3 * kPointerSize));
34938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
34948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
34958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->Plug(eax);
34968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
34978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
34988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
3501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
3502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
3503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
3504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
35073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
35083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
35093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
35128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(eax, GlobalObjectOperand());
3513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
3514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
35153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
35163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
35173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
35183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
35190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
3520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Call the JS runtime function via a call IC.
3524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Set(ecx, Immediate(expr->name()));
3525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
35268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
35270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
35280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Restore context register.
3529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
3531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the C runtime function.
3532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
3533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
35340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3538d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
3541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Property* prop = expr->expression()->AsProperty();
3543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
3544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (prop != NULL) {
35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (prop->is_synthetic()) {
35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          // Result of deleting parameters is false, even when they rewrite
35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          // to accesses on the arguments object.
35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          context()->Plug(false);
35501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        } else {
35510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(prop->obj());
35520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          VisitForStackValue(prop->key());
3553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(Smi::FromInt(strict_mode_flag())));
35541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          context()->Plug(eax);
3556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
3557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else if (var != NULL) {
3558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Delete of an unqualified identifier is disallowed in strict mode
3559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // but "delete this" is.
3560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
3561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (var->is_global()) {
3562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(GlobalObjectOperand());
3563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(var->name()));
3564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(Smi::FromInt(kNonStrictMode)));
3565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(eax);
3567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else if (var->AsSlot() != NULL &&
3568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                   var->AsSlot()->type() != Slot::LOOKUP) {
3569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Result of deleting non-global, non-dynamic variables is false.
3570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // The subexpression does not have side effects.
3571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(false);
3572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
3573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Non-global variable.  Call the runtime to try to delete from the
3574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // context where the variable was introduced.
3575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(context_register());
3576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(var->name()));
3577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
3578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(eax);
3579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
3581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Result of deleting non-property, non-variable reference is true.
3582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // The subexpression may have side effects.
3583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
3584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(true);
3585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
3586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
3587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
3588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
3590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
35920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(Factory::undefined_value());
3593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
35943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
3595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
3597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (context()->IsEffect()) {
3599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
3600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
3601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
3602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
3603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Label materialize_true, materialize_false;
3604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Label* if_true = NULL;
3605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Label* if_false = NULL;
3606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Label* fall_through = NULL;
3607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Notice that the labels are swapped.
3609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->PrepareTest(&materialize_true, &materialize_false,
3610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               &if_false, &if_true, &fall_through);
3611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (context()->IsTest()) ForwardBailoutToChild(expr);
3612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForControl(expr->expression(), if_true, if_false, fall_through);
3613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(if_false, if_true);  // Labels swapped.
3614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
3615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
3619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
36200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
36210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
36220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
36240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
3625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
3629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
36300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
3631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
3632d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ test(result_register(), Immediate(kSmiTagMask));
3633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ j(zero, &no_conversion);
36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ToNumberStub convert_stub;
36351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ CallStub(&convert_stub);
3636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
36370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(result_register());
3638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
3639d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
36414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::SUB: {
36424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (SUB)");
364380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3644ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      UnaryOverwriteMode overwrite =
3645ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
36460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      GenericUnaryOpStub stub(Token::SUB, overwrite, NO_UNARY_FLAGS);
36474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // GenericUnaryOpStub expects the argument to be in the
36484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      // accumulator register eax.
36490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
36504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
36510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
36524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
36534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
36544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
36554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    case Token::BIT_NOT: {
36564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
365780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The generic unary operation stub expects the argument to be
365880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // in the accumulator register eax.
36590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
366080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label done;
36610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_case = ShouldInlineSmiCase(expr->op());
36620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_case) {
36630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        NearLabel call_stub;
366480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ test(eax, Immediate(kSmiTagMask));
366580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ j(not_zero, &call_stub);
366680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ lea(eax, Operand(eax, kSmiTagMask));
366780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ not_(eax);
366880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ jmp(&done);
366980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&call_stub);
367080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
367180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      bool overwrite = expr->expression()->ResultOverwriteAllowed();
367280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UnaryOverwriteMode mode =
367380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
36740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      UnaryOpFlags flags = inline_smi_case
36750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          ? NO_UNARY_SMI_CODE_IN_STUB
36760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          : NO_UNARY_FLAGS;
36770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags);
36784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ CallStub(&stub);
36794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ bind(&done);
36800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
36814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
36824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
36834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
36863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3690d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
369280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
369380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
3695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // as the left-hand side.
3696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
3697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitForEffect(expr->expression());
3698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
3702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
3703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
3705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
3706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
3707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
3708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
3709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
3710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
3714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
3715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
37160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
37170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
3719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
37200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
3721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(Immediate(Smi::FromInt(0)));
3722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
3724402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Put the object both on the stack and in the accumulator.
37250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
3726402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(eax);
3727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
3728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
3729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prop->is_arguments_access()) {
3730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VariableProxy* obj_proxy = prop->obj()->AsVariableProxy();
3731086aeeaae12517475c22695a200be45495516549Ben Murdoch        MemOperand slot_operand =
3732086aeeaae12517475c22695a200be45495516549Ben Murdoch            EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
3733086aeeaae12517475c22695a200be45495516549Ben Murdoch        __ push(slot_operand);
3734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        __ mov(eax, Immediate(prop->key()->AsLiteral()->handle()));
3735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
3736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VisitForStackValue(prop->obj());
3737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        VisitForAccumulatorValue(prop->key());
3738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
3739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ mov(edx, Operand(esp, 0));
3740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(eax);
3741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
3742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We need a second deoptimization point after loading the value
3746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // in case evaluating the property load my have a side effect.
3747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailout(expr->increment(), TOS_REG);
3748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3749d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
37500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  NearLabel no_conversion;
375180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
375280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
375380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(zero, &no_conversion);
375480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
37551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ToNumberStub convert_stub;
37561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CallStub(&convert_stub);
3757d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
37583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
3760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
37610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
37620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
37630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
37640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
37650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
37660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
37670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ push(eax);
37680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
37690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
37700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ mov(Operand(esp, kPointerSize), eax);
37710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
37720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
37730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ mov(Operand(esp, 2 * kPointerSize), eax);
37740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
37750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3779d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
3780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  NearLabel stub_call, done;
3781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  JumpPatchSite patch_site(masm_);
3782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
378380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
3784d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3785d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3786d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3787d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3788d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3789d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ j(overflow, &stub_call);
3790d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
3791d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
3792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    patch_site.EmitJumpIfSmi(eax, &done);
3793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3794d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
3795d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
3796d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
3797d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3798d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
3799d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3800d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3801d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
3802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record position before stub call.
3804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
3805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
3807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(edx, eax);
3808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(eax, Immediate(Smi::FromInt(1)));
38091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
3810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EmitCallIC(stub.GetCode(), &patch_site);
3811d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
3812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in eax.
3814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
3815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
3816e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
3817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
38180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
38190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
38200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
3821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          context.Plug(eax);
38230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
38240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // For all contexts except EffectContext We have the result on
3825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
38260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
38270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
3831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
38320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
3833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context()->Plug(eax);
3835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
3838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ecx, prop->key()->AsLiteral()->handle());
38394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(edx);
3840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<Code> ic(Builtins::builtin(
3841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          is_strict() ? Builtins::StoreIC_Initialize_Strict
3842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      : Builtins::StoreIC_Initialize));
38430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
3844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
38460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
38470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
38500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(eax);
3851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3854e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
38556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(ecx);
38566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(edx);
3857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Handle<Code> ic(Builtins::builtin(
3858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
3859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      : Builtins::KeyedStoreIC_Initialize));
38600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitCallIC(ic, RelocInfo::CODE_TARGET);
3861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
38636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Result is on the stack
38640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
38650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
3866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
3867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
38680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(eax);
3869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
38723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
38733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
38743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
38753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
38760d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
387780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
38780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsEffect());
38790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsTest());
38800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
388180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
388280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Comment cmnt(masm_, "Global variable");
38838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(eax, GlobalObjectOperand());
388480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(ecx, Immediate(proxy->name()));
388580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
388680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
388780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
38880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    EmitCallIC(ic, RelocInfo::CODE_TARGET);
3889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr, TOS_REG);
38900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
389180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (proxy != NULL &&
38920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             proxy->var()->AsSlot() != NULL &&
38930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen             proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
389459151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
389559151504615d929945dc59db37bf1166937748c6Steve Block
389659151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
389759151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
38980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = proxy->var()->AsSlot();
389959151504615d929945dc59db37bf1166937748c6Steve Block    EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
390059151504615d929945dc59db37bf1166937748c6Steve Block
390159151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
390280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(esi);
390380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(Immediate(proxy->name()));
390480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr, TOS_REG);
390659151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
390759151504615d929945dc59db37bf1166937748c6Steve Block
39080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
390980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
391080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->HandleExpression(expr);
3912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
39143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
39153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
391680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::TryLiteralCompare(Token::Value op,
391780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Expression* left,
391880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Expression* right,
391980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* if_true,
392080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* if_false,
392180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Label* fall_through) {
392280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (op != Token::EQ && op != Token::EQ_STRICT) return false;
392380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
392480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check for the pattern: typeof <expression> == <string literal>.
392580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Literal* right_literal = right->AsLiteral();
392680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (right_literal == NULL) return false;
392780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Handle<Object> right_literal_value = right_literal->handle();
392880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!right_literal_value->IsString()) return false;
392980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  UnaryOperation* left_unary = left->AsUnaryOperation();
393080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
393180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Handle<String> check = Handle<String>::cast(right_literal_value);
393280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
39330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
39340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForTypeofValue(left_unary->expression());
39350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
39370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
393880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (check->Equals(Heap::number_symbol())) {
3939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_true);
394080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
394180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen           Factory::heap_number_map());
394280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
394380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::string_symbol())) {
3944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_false);
3945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
3946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(above_equal, if_false);
394780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
3948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
3949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              1 << Map::kIsUndetectable);
3950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
395180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::boolean_symbol())) {
395280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::true_value());
3953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
395480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::false_value());
395580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
395680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::undefined_symbol())) {
395780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::undefined_value());
3958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
3959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_false);
396080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
396180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
396280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
396380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(ecx, Immediate(1 << Map::kIsUndetectable));
396480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
396580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::function_symbol())) {
3966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_false);
3967e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CmpObjectType(eax, FIRST_FUNCTION_CLASS_TYPE, edx);
3968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(above_equal, if_true, if_false, fall_through);
396980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (check->Equals(Heap::object_symbol())) {
3970e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_false);
397180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::null_value());
397280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
3973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edx);
3974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(below, if_false);
3975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CmpInstanceType(edx, FIRST_FUNCTION_CLASS_TYPE);
3976e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(above_equal, if_false);
397780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
3978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
3979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              1 << Map::kIsUndetectable);
3980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
398180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
398280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
3983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
398480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
398580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return true;
3986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3989d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
399180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
3992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3993e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
3994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
3995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
3997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
3998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
399980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
40000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
40010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
400280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
400380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // First we try a fast inlined version of the compare when one of
400480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the operands is a literal.
400580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Token::Value op = expr->op();
400680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* left = expr->left();
400780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* right = expr->right();
400880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
40090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(if_true, if_false);
401080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return;
401180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
4012d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
40130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
4014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
4015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
40160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4017d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
4019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ cmp(eax, Factory::true_value());
402080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(equal, if_true, if_false, fall_through);
4021d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
40223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
40240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InstanceofStub stub(InstanceofStub::kNoFlags);
4026d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
4027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4028d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ test(eax, Operand(eax));
402980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The stub returns 0 for true.
403080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(zero, if_true, if_false, fall_through);
4031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4032d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4033d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
40350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
4036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
4037d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      bool strict = false;
403880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      switch (op) {
4039d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
4040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          strict = true;
4041d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Fall through
404280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        case Token::EQ:
4043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
4044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
4045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
4047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
4048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
4049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4050d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
4051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
4052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
4053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(edx, result_register());
4054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(eax);
4055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
4056d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
4057d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          // Reverse left and right sizes to obtain ECMA-262 conversion order.
4058d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
4059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          __ mov(edx, result_register());
4060d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(eax);
4061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
4063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
4064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          __ pop(edx);
4065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
4067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
4068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
4069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
4070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
4071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
40720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
4073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JumpPatchSite patch_site(masm_);
40740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
40750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        NearLabel slow_case;
407680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ mov(ecx, Operand(edx));
407780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ or_(ecx, Operand(eax));
4078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        patch_site.EmitJumpIfNotSmi(ecx, &slow_case);
407980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ cmp(edx, Operand(eax));
408080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Split(cc, if_true, if_false, NULL);
408180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
408280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
4083d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Record position and call the compare IC.
4085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SetSourcePosition(expr->position());
4086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Handle<Code> ic = CompareIC::GetUninitialized(op);
4087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      EmitCallIC(ic, &patch_site);
4088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ test(eax, Operand(eax));
409180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(cc, if_true, if_false, fall_through);
4092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
40933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
40943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4095e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
4096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
40970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
4098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
410180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
410280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
410380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
410480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
410580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
41060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
41070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
410880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
41090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(expr->expression());
4110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
411280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ cmp(eax, Factory::null_value());
411380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (expr->is_strict()) {
411480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
411580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
411680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
411780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(eax, Factory::undefined_value());
411880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
411980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(eax, Immediate(kSmiTagMask));
412080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(zero, if_false);
412180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // It can be an undetectable object.
412280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
412380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset));
412480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(edx, Immediate(1 << Map::kIsUndetectable));
412580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
412680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
41270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
412880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
412980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
413080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4131d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
41330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
41340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
41350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
41360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
41370d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
41380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return eax;
4139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
41420d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
41430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return esi;
41440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
41470d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
41480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(mode == RelocInfo::CODE_TARGET ||
41490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen         mode == RelocInfo::CODE_TARGET_CONTEXT);
4150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (ic->kind()) {
4151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Code::LOAD_IC:
4152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      __ IncrementCounter(&Counters::named_load_full, 1);
4153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Code::KEYED_LOAD_IC:
4155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      __ IncrementCounter(&Counters::keyed_load_full, 1);
4156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Code::STORE_IC:
4158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      __ IncrementCounter(&Counters::named_store_full, 1);
4159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Code::KEYED_STORE_IC:
4161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      __ IncrementCounter(&Counters::keyed_store_full, 1);
4162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
4163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
4164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
41660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ call(ic, mode);
41670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Crankshaft doesn't need patching of inlined loads and stores.
4169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // When compiling the snapshot we need to produce code that works
4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // with and without Crankshaft.
4171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (V8::UseCrankshaft() && !Serializer::enabled()) {
4172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
4173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
41750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // If we're calling a (keyed) load or store stub, we have to mark
41760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // the call as containing no inlined code so we will not attempt to
41770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // patch it.
41780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  switch (ic->kind()) {
41790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::LOAD_IC:
41800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::KEYED_LOAD_IC:
41810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::STORE_IC:
41820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    case Code::KEYED_STORE_IC:
41830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ nop();  // Signals no inlined code.
41840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      break;
41850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    default:
41860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Do nothing.
41870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      break;
41880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
41890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
4193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  switch (ic->kind()) {
4194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Code::LOAD_IC:
4195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ IncrementCounter(&Counters::named_load_full, 1);
4196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
4197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Code::KEYED_LOAD_IC:
4198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ IncrementCounter(&Counters::keyed_load_full, 1);
4199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
4200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Code::STORE_IC:
4201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ IncrementCounter(&Counters::named_store_full, 1);
4202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
4203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Code::KEYED_STORE_IC:
4204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ IncrementCounter(&Counters::keyed_store_full, 1);
4205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    default:
4206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
4207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
4208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ call(ic, RelocInfo::CODE_TARGET);
4210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (patch_site != NULL && patch_site->is_bound()) {
4211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    patch_site->EmitPatchInfo();
4212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
4213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ nop();  // Signals no inlined code.
4214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
4215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
4216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(ebp, frame_offset), value);
42213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
42223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
42233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4224d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
422559151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(dst, ContextOperand(esi, context_index));
4226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
4230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
4231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
4233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
4234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(edx));
4235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(edx, Operand(esp, 0));
4236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sub(Operand(edx), Immediate(masm_->CodeObject()));
4237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
4238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, kSmiTag);
4239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(edx, Operand(edx));  // Convert to smi.
4240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(esp, 0), edx);
4241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
4242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
4243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4246d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
4247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(edx));
4248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Restore result register from stack.
4249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
4250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
4251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(edx, Operand(esp, 0));
4252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ sar(edx, 1);  // Convert smi to int.
4253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(Operand(edx), Immediate(masm_->CodeObject()));
4254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(esp, 0), edx);
4255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // And return.
4256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
4257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __
4261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
42623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
4263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
4265