13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h"
35e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include "debug.h"
36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "isolate-inl.h"
383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h"
396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#include "stub-cache.h"
413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 {
433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal {
443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
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
60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJumpIfNotSmi(Register reg,
61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Label* target,
62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Label::Distance distance = Label::kFar) {
63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ test(reg, Immediate(kSmiTagMask));
64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitJump(not_carry, target, distance);  // Always taken before patched.
65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJumpIfSmi(Register reg,
68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     Label* target,
69257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     Label::Distance distance = Label::kFar) {
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ test(reg, Immediate(kSmiTagMask));
71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitJump(carry, target, distance);  // Never taken before patched.
72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void EmitPatchInfo() {
753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (patch_site_.is_bound()) {
763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(is_int8(delta_to_patch_site));
783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ test(eax, Immediate(delta_to_patch_site));
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      info_emitted_ = true;
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ nop();  // Signals no inlined code.
843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // jc will be patched with jz, jnc will become jnz.
89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitJump(Condition cc, Label* target, Label::Distance distance) {
90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!patch_site_.is_bound() && !info_emitted_);
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(cc == carry || cc == not_carry);
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ bind(&patch_site_);
93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(cc, target, distance);
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MacroAssembler* masm_;
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label patch_site_;
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool info_emitted_;
100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(jkummerow): Obsolete as soon as x64 is updated. Remove.
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint FullCodeGenerator::self_optimization_header_size() {
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return 13;
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function.  On entry to the function the receiver
1123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the
1133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them.  The actual argument count matches the
1143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function.
1153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are:
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   o edi: the JS function object being called (i.e. ourselves)
1183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o esi: our context
1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o ebp: our caller's frame pointer
1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//   o esp: stack pointer (pointing to return address)
1213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block//
1223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame.  Please see JavaScriptFrameConstants in
1233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-ia32.h for its layout.
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() {
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompilationInfo* info = info_;
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handler_table_ =
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget)));
1303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  SetFunctionPosition(function());
1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comment cmnt(masm_, "[ function compiled by full code generator");
1323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
133f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
134f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (strlen(FLAG_stop_at) > 0 &&
135f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
136f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ int3();
137f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
138f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
139f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Strict mode functions and builtins need to replace the receiver
1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // with undefined when called as functions (without an explicit
1423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // receiver object). ecx is zero for method calls and non-zero for
1433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // function calls.
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!info->is_classic_mode() || info->is_native()) {
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label ok;
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ test(ecx, ecx);
147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(zero, &ok, Label::kNear);
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // +1 for return address.
1493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ecx, Operand(esp, receiver_offset));
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(ecx, &ok);
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CmpObjectType(ecx, JS_GLOBAL_PROXY_TYPE, ecx);
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &ok, Label::kNear);
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ mov(Operand(esp, receiver_offset),
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           Immediate(isolate()->factory()->undefined_value()));
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&ok);
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MANUAL indicates that the scope shouldn't actually generate code to set up
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done below).
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
164756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(ebp);  // Caller's frame pointer.
165756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ mov(ebp, esp);
166756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(esi);  // Callee's context.
167756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(edi);  // Callee's JS Function.
168756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
169756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  { Comment cmnt(masm_, "[ Allocate locals");
1703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int locals_count = info->scope()->num_stack_slots();
171756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (locals_count == 1) {
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ push(Immediate(isolate()->factory()->undefined_value()));
173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else if (locals_count > 1) {
17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ mov(eax, Immediate(isolate()->factory()->undefined_value()));
175756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      for (int i = 0; i < locals_count; i++) {
176756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ push(eax);
177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
179756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
181756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool function_in_register = true;
1824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
183756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Possibly allocate a local context.
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (heap_slots > 0) {
186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate local context");
187756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Argument to NewContext is the function, which is still in edi.
188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(edi);
189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      FastNewContextStub stub(heap_slots);
191756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ CallStub(&stub);
192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ CallRuntime(Runtime::kNewFunctionContext, 1);
194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    function_in_register = false;
196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Context is returned in both eax and esi.  It replaces the context
197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // passed to us.  It's saved in the stack and kept live in esi.
198756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
200756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Copy parameters into context if necessary.
2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    for (int i = 0; i < num_parameters; i++) {
203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Variable* var = scope()->parameter(i);
204589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick            (num_parameters - 1 - i) * kPointerSize;
207756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Load parameter from stack.
208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(eax, Operand(ebp, parameter_offset));
209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        // Store it in the context.
210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        int context_offset = Context::SlotOffset(var->index());
211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        __ mov(Operand(esi, context_offset), eax);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier. This clobbers eax and ebx.
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(esi,
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  context_offset,
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  eax,
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  ebx,
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  kDontSaveFPRegs);
218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
220756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Variable* arguments = scope()->arguments();
223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (arguments != NULL) {
224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Function uses arguments object.
225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Comment cmnt(masm_, "[ Allocate arguments object");
226756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (function_in_register) {
227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(edi);
228756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    } else {
229756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Receiver is just before the parameters on the caller's stack.
2323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num_parameters = info->scope()->num_parameters();
2333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int offset = num_parameters * kPointerSize;
234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ lea(edx,
235756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
236756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ push(edx);
2373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ SafePush(Immediate(Smi::FromInt(num_parameters)));
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Arguments to ArgumentsAccessStub:
239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    //   function, receiver address, parameter count.
240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // The stub will rewrite receiver and parameter count if the previous
241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // stack frame was an arguments adapter frame.
2423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ArgumentsAccessStub::Type type;
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!is_classic_mode()) {
2443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      type = ArgumentsAccessStub::NEW_STRICT;
2453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (function()->has_duplicate_parameters()) {
2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
2493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ArgumentsAccessStub stub(type);
251756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SetVar(arguments, eax, ebx, edx);
254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace) {
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ CallRuntime(Runtime::kTraceEnter, 0);
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Visit the declarations and body unless there is an illegal
2611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // redeclaration.
2621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (scope()->HasIllegalRedeclaration()) {
2631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Comment cmnt(masm_, "[ Declarations");
2641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    scope()->VisitIllegalRedeclaration(this);
2651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
267589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
2681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    { Comment cmnt(masm_, "[ Declarations");
2691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // For named function expressions, declare the function name as a
2701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // constant.
2711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (scope()->is_function_scope() && scope()->function() != NULL) {
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VariableProxy* proxy = scope()->function();
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(proxy->var()->mode() == CONST ||
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               proxy->var()->mode() == CONST_HARMONY);
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        EmitDeclaration(proxy, proxy->var()->mode(), NULL);
2771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
2781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      VisitDeclarations(scope()->declarations());
2791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
2803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    { Comment cmnt(masm_, "[ Stack check");
282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label ok;
2841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ExternalReference stack_limit =
28544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::address_of_stack_limit(isolate());
2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cmp(esp, Operand::StaticVariable(stack_limit));
287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ j(above_equal, &ok, Label::kNear);
2881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      StackCheckStub stub;
2891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ CallStub(&stub);
2901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&ok);
2911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
2921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    { Comment cmnt(masm_, "[ Body");
2941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ASSERT(loop_depth() == 0);
2951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      VisitStatements(function()->body());
2961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ASSERT(loop_depth() == 0);
2971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
2983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Always emit a 'return undefined' in case control fell off the end of
3011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the body.
3023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  { Comment cmnt(masm_, "[ return <undefined>;");
30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ mov(eax, isolate()->factory()->undefined_value());
3047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    EmitReturnSequence();
305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
309db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() {
310db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  __ Set(eax, Immediate(Smi::FromInt(0)));
311db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch}
312db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
313db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, Immediate(profiling_counter_));
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Immediate(Smi::FromInt(delta)));
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() {
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int reset_value = FLAG_interrupt_budget;
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Self-optimization is a one-off thing: if it fails, don't try again.
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    reset_value = Smi::kMaxValue;
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->IsDebuggerActive()) {
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Detect debug break requests as soon as possible.
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    reset_value = 10;
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, Immediate(profiling_counter_));
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Immediate(Smi::FromInt(reset_value)));
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kMaxBackEdgeWeight = 127;
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kBackEdgeDistanceDivisor = 100;
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStackCheck(IterationStatement* stmt,
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* back_edge_target) {
343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Comment cmnt(masm_, "[ Stack check");
344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label ok;
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_count_based_interrupts) {
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int weight = 1;
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_weighted_back_edges) {
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(back_edge_target->is_bound());
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      weight = Min(kMaxBackEdgeWeight,
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Max(1, distance / kBackEdgeDistanceDivisor));
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitProfilingCounterDecrement(weight);
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(positive, &ok, Label::kNear);
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InterruptStub stub;
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Count based interrupts happen often enough when they are enabled
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // that the additional stack checks are not necessary (they would
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // only check for interrupts).
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference stack_limit =
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::address_of_stack_limit(isolate());
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(esp, Operand::StaticVariable(stack_limit));
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &ok, Label::kNear);
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    StackCheckStub stub;
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
370086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of this PC offset to the OSR id.  This is used to find
371086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the AST id from the unoptimized code in order to use it as a key into
372086aeeaae12517475c22695a200be45495516549Ben Murdoch  // the deoptimization input data found in the optimized code.
373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordStackCheck(stmt->OsrEntryId());
374086aeeaae12517475c22695a200be45495516549Ben Murdoch
375086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Loop stack checks can be patched to perform on-stack replacement. In
376086aeeaae12517475c22695a200be45495516549Ben Murdoch  // order to decide whether or not to perform OSR we embed the loop depth
377086aeeaae12517475c22695a200be45495516549Ben Murdoch  // in a test instruction after the call so we can extract it from the OSR
378086aeeaae12517475c22695a200be45495516549Ben Murdoch  // builtin.
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(loop_depth() > 0);
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ test(eax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker)));
381086aeeaae12517475c22695a200be45495516549Ben Murdoch
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_count_based_interrupts) {
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitProfilingCounterReset();
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
386086aeeaae12517475c22695a200be45495516549Ben Murdoch  __ bind(&ok);
387086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
388086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Record a mapping of the OSR id to this PC.  This is used if the OSR
389086aeeaae12517475c22695a200be45495516549Ben Murdoch  // entry becomes the target of a bailout.  We don't expect it to be, but
390086aeeaae12517475c22695a200be45495516549Ben Murdoch  // we want it to work if it is.
391086aeeaae12517475c22695a200be45495516549Ben Murdoch  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() {
396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Return sequence");
397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (return_label_.is_bound()) {
398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ jmp(&return_label_);
399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Common return label
401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ bind(&return_label_);
4023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (FLAG_trace) {
4033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(eax);
4043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ CallRuntime(Runtime::kTraceExit, 1);
4053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_interrupt_at_exit || FLAG_self_optimization) {
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Pretend that the exit is a backwards jump to the entry.
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int weight = 1;
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (info_->ShouldSelfOptimize()) {
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        weight = FLAG_interrupt_budget / FLAG_self_opt_count;
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (FLAG_weighted_back_edges) {
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int distance = masm_->pc_offset();
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        weight = Min(kMaxBackEdgeWeight,
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Max(1, distance / kBackEdgeDistanceDivisor));
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitProfilingCounterDecrement(weight);
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label ok;
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(positive, &ok, Label::kNear);
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(eax);
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        InterruptStub stub;
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallStub(&stub);
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(eax);
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitProfilingCounterReset();
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&ok);
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Add a label for checking the size of the code used for returning.
433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Label check_exit_codesize;
434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    masm_->bind(&check_exit_codesize);
435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(function()->end_position() - 1);
4373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ RecordJSReturn();
4383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Do not use the leave instruction here because it is too short to
4393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // patch with the code required by the debugger.
4403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(esp, ebp);
4413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ pop(ebp);
4421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
4441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret(arguments_bytes, ecx);
445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
4461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check that the size of the code used for returning is large enough
4471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // for the debugger's requirements.
4481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(Assembler::kJSReturnSequenceLength <=
4491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
455589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const {
456589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
4570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
460589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
461589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
462589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand operand = codegen()->VarOperand(var, result_register());
4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Memory operands can be pushed directly.
470589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ push(operand);
471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
474589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const {
4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  codegen()->GetVar(result_register(), var);
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
4790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4820d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
4830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Heap::RootListIndex index) const {
4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  UNREACHABLE();  // Not used on IA32.
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Handle<Object> lit) const {
510053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (lit->IsSmi()) {
511053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    __ SafeSet(result_register(), Immediate(lit));
512053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
513053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    __ Set(result_register(), Immediate(lit));
514053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
519053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (lit->IsSmi()) {
520053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    __ SafePush(Immediate(lit));
521053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  } else {
522053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    __ push(Immediate(lit));
523053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5270d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
5320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
5330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (false_label_ != fall_through_) __ jmp(false_label_);
5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsTrue() || lit->IsJSObject()) {
536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (true_label_ != fall_through_) __ jmp(true_label_);
5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsString()) {
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (String::cast(*lit)->length() == 0) {
539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else if (lit->IsSmi()) {
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (Smi::cast(*lit)->value() == 0) {
545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (false_label_ != fall_through_) __ jmp(false_label_);
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (true_label_ != fall_through_) __ jmp(true_label_);
5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // For simplicity we always test the accumulator register.
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(result_register(), lit);
5523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    codegen()->DoTest(this);
553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
5580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                   Register reg) const {
559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(count > 0);
5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    int count,
5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Register reg) const {
5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5730d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Register reg) const {
5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (count > 1) __ Drop(count - 1);
5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(Operand(esp, 0), reg);
578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                 Register reg) const {
5830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(count > 0);
5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(count);
5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
5883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            Label* materialize_false) const {
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(materialize_true == materialize_false);
5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(
6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
6030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
60444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(result_register(), isolate()->factory()->true_value());
605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
6060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(result_register(), isolate()->factory()->false_value());
6080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(
6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false) const {
615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_true);
61744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ push(Immediate(isolate()->factory()->true_value()));
618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(materialize_false);
62044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ push(Immediate(isolate()->factory()->false_value()));
6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&done);
6220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          Label* materialize_false) const {
6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(materialize_true == true_label_);
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(materialize_false == false_label_);
6290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
63744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> value = flag
63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? isolate()->factory()->true_value()
63944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : isolate()->factory()->false_value();
6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(result_register(), value);
6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6440d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> value = flag
64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? isolate()->factory()->true_value()
64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : isolate()->factory()->false_value();
6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(Immediate(value));
6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(),
654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true,
655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          true_label_,
656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          false_label_);
6570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (flag) {
6580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (true_label_ != fall_through_) __ jmp(true_label_);
6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
6600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (false_label_ != fall_through_) __ jmp(false_label_);
661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition,
6663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               Label* if_true,
66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* if_false,
66880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                               Label* fall_through) {
6693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ToBooleanStub stub(result_register());
670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
67169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ CallStub(&stub, condition->test_id());
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ test(result_register(), result_register());
67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The stub returns nonzero for true.
67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
67580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc,
67980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_true,
68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* if_false,
68180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                              Label* fall_through) {
68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (if_false == fall_through) {
68380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
68480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (if_true == fall_through) {
68580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(NegateCondition(cc), if_false);
68680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
68780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(cc, if_true);
68880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(if_false);
689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
693589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) {
694589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsStackAllocated());
695589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Offset is negative because higher indexes are at lower addresses.
696589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int offset = -var->index() * kPointerSize;
697589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Adjust by a (parameter or local) base offset.
698589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsParameter()) {
699589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
700589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
701589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    offset += JavaScriptFrameConstants::kLocal0Offset;
702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
703589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return Operand(ebp, offset);
704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
707589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
708589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
710589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int context_chain_length = scope()->ContextChainLength(var->scope());
711589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ LoadContext(scratch, context_chain_length);
712589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return ContextOperand(scratch, var->index());
713589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
714589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return StackOperand(var);
715589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, dest);
722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(dest, location);
723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
724589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
725589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
726589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var,
727589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register src,
728589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch0,
729589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                               Register scratch1) {
730589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
731589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch0.is(src));
732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch0.is(scratch1));
733589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(!scratch1.is(src));
734589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  MemOperand location = VarOperand(var, scratch0);
735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(location, src);
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit the write barrier code if the location is in the heap.
738589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsContextSlot()) {
739589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int offset = Context::SlotOffset(var->index());
740589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     bool should_normalize,
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_true,
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                     Label* if_false) {
750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Only prepare for bailouts before splits if we're in a test
751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // context. Otherwise, we let the Visit function deal with the
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // preparation to avoid preparing with the same AST id twice.
753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!context()->IsTest() || !info_->IsOptimizable()) return;
754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label skip;
756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (should_normalize) __ jmp(&skip, Label::kNear);
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailout(expr, TOS_REG);
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (should_normalize) {
75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(eax, isolate()->factory()->true_value());
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Split(equal, if_true, if_false, NULL);
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ bind(&skip);
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
766589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        VariableMode mode,
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        FunctionLiteral* function) {
769589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // If it was not possible to allocate the variable at compile time, we
770589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // need to "declare" it at runtime to make sure it actually exists in the
771589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // local context.
772589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Variable* variable = proxy->var();
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool binding_needs_init = (function == NULL) &&
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (mode == CONST || mode == CONST_HARMONY || mode == LET);
775589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (variable->location()) {
776589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED:
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ++global_count_;
778589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
779589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
780589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
781589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
78269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
783589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
78469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForAccumulatorValue(function);
785589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ mov(StackOperand(variable), result_register());
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
787589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ mov(StackOperand(variable),
78969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               Immediate(isolate()->factory()->the_hole_value()));
790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
79169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT:
79469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // The variable in the decl always resides in the current function
79569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // context.
79669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
79769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (FLAG_debug_code) {
79869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // Check that we're not inside a with or catch context.
79969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
80069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ cmp(ebx, isolate()->factory()->with_context_map());
80169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Check(not_equal, "Declaration in with context.");
80269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ cmp(ebx, isolate()->factory()->catch_context_map());
80369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ Check(not_equal, "Declaration in catch context.");
8041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
80569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
806589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
80769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForAccumulatorValue(function);
808589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ mov(ContextOperand(esi, variable->index()), result_register());
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We know that we have written a function, which is not a smi.
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(esi,
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Context::SlotOffset(variable->index()),
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result_register(),
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  ecx,
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  kDontSaveFPRegs,
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  EMIT_REMEMBERED_SET,
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  OMIT_SMI_CHECK);
817589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
819589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Comment cmnt(masm_, "[ Declaration");
820589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ mov(ContextOperand(esi, variable->index()),
82169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               Immediate(isolate()->factory()->the_hole_value()));
82269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // No write barrier since the hole value is in old space.
823589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
8261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
827589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
828589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "[ Declaration");
82969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ push(esi);
83069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ push(Immediate(variable->name()));
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Declaration nodes are always introduced in one of four modes.
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(mode == VAR ||
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == CONST ||
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == CONST_HARMONY ||
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             mode == LET);
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY)
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? READ_ONLY : NONE;
83869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ push(Immediate(Smi::FromInt(attr)));
83969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Push initial value, if any.
84069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Note: For variables we must not push an initial value (such as
84169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // 'undefined') because we may have a (legal) redeclaration and we
84269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // must not destroy the current value.
84369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (function != NULL) {
84469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        VisitForStackValue(function);
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (binding_needs_init) {
84669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ push(Immediate(isolate()->factory()->the_hole_value()));
84769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
848589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ push(Immediate(Smi::FromInt(0)));  // Indicates no initial value.
84969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
85069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ CallRuntime(Runtime::kDeclareContextSlot, 4);
85169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      break;
852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
857d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
8583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Call the runtime to declare the globals.
8593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(esi);  // The context is the first argument.
8603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(pairs));
861589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ push(Immediate(Smi::FromInt(DeclareGlobalsFlags())));
862589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ CallRuntime(Runtime::kDeclareGlobals, 3);
8633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Return value is ignored.
8643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SwitchStatement");
869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Breakable nested_statement(this, stmt);
870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Keep the switch value on the stack until a case matches.
8730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->tag());
874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<CaseClause*>* clauses = stmt->cases();
877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label next_test;  // Recycled for each test.
880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the tests with branches to their bodies.
881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
8838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clause->body_target()->Unuse();
8841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // The default is not a test, but remember it as final fall through.
886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (clause->is_default()) {
887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      default_clause = clause;
888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      continue;
889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case comparison");
892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ bind(&next_test);
893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    next_test.Unuse();
894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Compile the label expression.
8960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(clause->label());
897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
89880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Perform the comparison as if via '==='.
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(edx, Operand(esp, 0));  // Switch value.
9000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JumpPatchSite patch_site(masm_);
9020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (inline_smi_code) {
903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label slow_case;
90480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ mov(ecx, edx);
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ or_(ecx, eax);
906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(edx, eax);
90980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(not_equal, &next_test);
91080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ Drop(1);  // Switch value is no longer needed.
9118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      __ jmp(clause->body_target());
91280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&slow_case);
91380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Record position before stub call for type feedback.
916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(clause->position());
917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
9193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    patch_site.EmitPatchInfo();
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ test(eax, eax);
921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(not_equal, &next_test);
922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Drop(1);  // Switch value is no longer needed.
9238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ jmp(clause->body_target());
924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
9253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Discard the test value and jump to the default if present, otherwise to
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the end of the statement.
928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&next_test);
929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ Drop(1);  // Switch value is no longer needed.
930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (default_clause == NULL) {
93169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ jmp(nested_statement.break_label());
932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
9338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ jmp(default_clause->body_target());
934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Compile all the case bodies.
937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < clauses->length(); i++) {
938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ Case body");
939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CaseClause* clause = clauses->at(i);
9408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ bind(clause->body_target());
94144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    VisitStatements(clause->statements());
943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
94569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(nested_statement.break_label());
946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ ForInStatement");
952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SetStatementPosition(stmt);
953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label loop, exit;
955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ForIn loop_statement(this, stmt);
956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  increment_loop_depth();
957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the object to enumerate over. Both SpiderMonkey and JSC
959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ignore null and undefined in contrast to the specification; see
960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ECMA-262 section 12.6.4.
9610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(stmt->enumerable());
96244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(eax, isolate()->factory()->undefined_value());
963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
96444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(eax, isolate()->factory()->null_value());
965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, &exit);
966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the object to a JS object.
970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label convert, done_convert;
9713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &convert, Label::kNear);
9723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &done_convert, Label::kNear);
974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&convert);
975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done_convert);
978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for proxies.
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label call_runtime, use_cache, fixed_array;
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(below_equal, &call_runtime);
9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
98659151504615d929945dc59db37bf1166937748c6Steve Block  // Check cache validity in generated code. This is a fast case for
98759151504615d929945dc59db37bf1166937748c6Steve Block  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
98859151504615d929945dc59db37bf1166937748c6Steve Block  // guarantee cache validity, call the runtime system to check cache
98959151504615d929945dc59db37bf1166937748c6Steve Block  // validity or get the property names in a fixed array.
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckEnumCache(&call_runtime);
99159151504615d929945dc59db37bf1166937748c6Steve Block
99259151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&use_cache, Label::kNear);
994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the set of properties to enumerate.
99659151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&call_runtime);
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(eax);
998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block         isolate()->factory()->meta_map());
10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &fixed_array);
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a map in register eax. Get the enumeration cache from it.
100559151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&use_cache);
1006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(eax, ecx);
1007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the four remaining stack slots.
1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Map.
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(edx);  // Enumeration cache.
1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Enumeration cache length (as smi).
1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&loop);
1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We got a fixed array in register eax. Iterate through that.
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label non_proxy;
1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&fixed_array);
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewJSGlobalPropertyCell(
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<Object>(
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker)));
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordTypeFeedbackCell(stmt->PrepareId(), cell);
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(ebx, cell);
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Immediate(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, Immediate(Smi::FromInt(1)));  // Smi indicates slow check
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ecx, Operand(esp, 0 * kPointerSize));  // Get enumerated object
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx);
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(above, &non_proxy);
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, Immediate(Smi::FromInt(0)));  // Zero indicates proxy
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_proxy);
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(ebx);  // Smi
10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(eax);  // Array
1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(eax);  // Fixed array length (as smi).
1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(Immediate(Smi::FromInt(0)));  // Initial index.
1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for doing the condition check.
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&loop);
1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(esp, 0 * kPointerSize));  // Get the current index.
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(eax, Operand(esp, 1 * kPointerSize));  // Compare to the array length.
104969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ j(above_equal, loop_statement.break_label());
1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the current entry of the array into register ebx.
1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(esp, 2 * kPointerSize));
1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
1054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the expected map from the stack or a smi in the
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // permanent slow case into register edx.
1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, Operand(esp, 3 * kPointerSize));
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the expected map still matches that of the enumerable.
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If not, we may have to filter the key.
1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label update_each;
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ecx, Operand(esp, 4 * kPointerSize));
1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
1064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &update_each, Label::kNear);
1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For proxies, no filtering is done.
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(Smi::FromInt(0) == 0);
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ test(edx, edx);
10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(zero, &update_each);
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert the entry to a string or null if it isn't a property
1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // anymore. If the property has been removed while iterating, we
1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // just skip it.
1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(ecx);  // Enumerable.
1076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(ebx);  // Current entry.
1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ test(eax, eax);
107969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ j(equal, loop_statement.continue_label());
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, eax);
1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the 'each' property or variable from the possibly filtered
1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // entry in register ebx.
1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&update_each);
1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(result_register(), ebx);
1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Perform the assignment as if via '='.
1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { EffectContext context(this);
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAssignment(stmt->each());
1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for the body of the loop.
1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Visit(stmt->body());
1093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate code for going to the next element by incrementing the
1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // index (smi) stored on top of the stack.
109669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitStackCheck(stmt, &loop);
1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&loop);
1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Remove the pointers stored on the stack.
110369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(esp, Immediate(5 * kPointerSize));
1105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Exit and decrement the loop depth.
11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  decrement_loop_depth();
1110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
11148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                       bool pretenure) {
1115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Use the fast case closure allocation code that allocates in new
1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // space for nested functions that don't need literals cloning. If
1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // we're running with the --always-opt or the --prepare-always-opt
1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // flag, we need to use the runtime function so that the new function
1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // we are creating here gets a chance to have its code optimized and
1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // doesn't just get a copy of the existing unoptimized code.
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_always_opt &&
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      !FLAG_prepare_always_opt &&
112344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      !pretenure &&
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      scope()->is_function_scope() &&
112544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      info->num_literals() == 0) {
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastNewClosureStub stub(info->language_mode());
1127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(info));
1128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
1129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(esi);
1131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(Immediate(info));
11328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(Immediate(pretenure
113344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      ? isolate()->factory()->true_value()
113444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      : isolate()->factory()->false_value()));
11358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CallRuntime(Runtime::kNewClosure, 3);
1136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
11370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
11383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
11423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ VariableProxy");
11433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  EmitVariableLoad(expr);
1144e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1145e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
1148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      TypeofState typeof_state,
1149589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                      Label* slow) {
115059151504615d929945dc59db37bf1166937748c6Steve Block  Register context = esi;
115159151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = edx;
115259151504615d929945dc59db37bf1166937748c6Steve Block
115359151504615d929945dc59db37bf1166937748c6Steve Block  Scope* s = scope();
115459151504615d929945dc59db37bf1166937748c6Steve Block  while (s != NULL) {
115559151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (s->calls_non_strict_eval()) {
115759151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
115859151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
115959151504615d929945dc59db37bf1166937748c6Steve Block               Immediate(0));
116059151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
116159151504615d929945dc59db37bf1166937748c6Steve Block      }
116259151504615d929945dc59db37bf1166937748c6Steve Block      // Load next context in chain.
11633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
116459151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering esi.
116559151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
116659151504615d929945dc59db37bf1166937748c6Steve Block    }
116759151504615d929945dc59db37bf1166937748c6Steve Block    // If no outer scope calls eval, we do not need to check more
116859151504615d929945dc59db37bf1166937748c6Steve Block    // context extensions.  If we have reached an eval scope, we check
116959151504615d929945dc59db37bf1166937748c6Steve Block    // all extensions from this point.
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
117159151504615d929945dc59db37bf1166937748c6Steve Block    s = s->outer_scope();
117259151504615d929945dc59db37bf1166937748c6Steve Block  }
117359151504615d929945dc59db37bf1166937748c6Steve Block
117459151504615d929945dc59db37bf1166937748c6Steve Block  if (s != NULL && s->is_eval_scope()) {
117559151504615d929945dc59db37bf1166937748c6Steve Block    // Loop up the context chain.  There is no frame effect so it is
117659151504615d929945dc59db37bf1166937748c6Steve Block    // safe to use raw labels here.
1177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label next, fast;
117859151504615d929945dc59db37bf1166937748c6Steve Block    if (!context.is(temp)) {
117959151504615d929945dc59db37bf1166937748c6Steve Block      __ mov(temp, context);
118059151504615d929945dc59db37bf1166937748c6Steve Block    }
118159151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&next);
118259151504615d929945dc59db37bf1166937748c6Steve Block    // Terminate at global context.
118359151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(FieldOperand(temp, HeapObject::kMapOffset),
118444f0eee88ff00398ff7f715fab053374d808c90dSteve Block           Immediate(isolate()->factory()->global_context_map()));
1185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &fast, Label::kNear);
118659151504615d929945dc59db37bf1166937748c6Steve Block    // Check that extension is NULL.
118759151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
118859151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, slow);
118959151504615d929945dc59db37bf1166937748c6Steve Block    // Load next context in chain.
11903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
119159151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(&next);
119259151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&fast);
119359151504615d929945dc59db37bf1166937748c6Steve Block  }
119459151504615d929945dc59db37bf1166937748c6Steve Block
119559151504615d929945dc59db37bf1166937748c6Steve Block  // All extension objects were empty and it is safe to use a global
119659151504615d929945dc59db37bf1166937748c6Steve Block  // load IC call.
11978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(eax, GlobalObjectOperand());
1198589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(ecx, var->name());
119944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
120059151504615d929945dc59db37bf1166937748c6Steve Block  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
120159151504615d929945dc59db37bf1166937748c6Steve Block      ? RelocInfo::CODE_TARGET
120259151504615d929945dc59db37bf1166937748c6Steve Block      : RelocInfo::CODE_TARGET_CONTEXT;
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, mode);
120459151504615d929945dc59db37bf1166937748c6Steve Block}
120559151504615d929945dc59db37bf1166937748c6Steve Block
120659151504615d929945dc59db37bf1166937748c6Steve Block
1207589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                                Label* slow) {
1209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ASSERT(var->IsContextSlot());
121059151504615d929945dc59db37bf1166937748c6Steve Block  Register context = esi;
121159151504615d929945dc59db37bf1166937748c6Steve Block  Register temp = ebx;
121259151504615d929945dc59db37bf1166937748c6Steve Block
1213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
121459151504615d929945dc59db37bf1166937748c6Steve Block    if (s->num_heap_slots() > 0) {
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (s->calls_non_strict_eval()) {
121659151504615d929945dc59db37bf1166937748c6Steve Block        // Check that extension is NULL.
121759151504615d929945dc59db37bf1166937748c6Steve Block        __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
121859151504615d929945dc59db37bf1166937748c6Steve Block               Immediate(0));
121959151504615d929945dc59db37bf1166937748c6Steve Block        __ j(not_equal, slow);
122059151504615d929945dc59db37bf1166937748c6Steve Block      }
12213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
122259151504615d929945dc59db37bf1166937748c6Steve Block      // Walk the rest of the chain without clobbering esi.
122359151504615d929945dc59db37bf1166937748c6Steve Block      context = temp;
122459151504615d929945dc59db37bf1166937748c6Steve Block    }
122559151504615d929945dc59db37bf1166937748c6Steve Block  }
122659151504615d929945dc59db37bf1166937748c6Steve Block  // Check that last extension is NULL.
122759151504615d929945dc59db37bf1166937748c6Steve Block  __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
122859151504615d929945dc59db37bf1166937748c6Steve Block  __ j(not_equal, slow);
12291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // This function is used only for loads, not stores, so it's safe to
12311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // return an esi-based operand (the write barrier cannot be allowed to
12321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // destroy the esi register).
1233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return ContextOperand(context, var->index());
123459151504615d929945dc59db37bf1166937748c6Steve Block}
123559151504615d929945dc59db37bf1166937748c6Steve Block
123659151504615d929945dc59db37bf1166937748c6Steve Block
1237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1238589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  TypeofState typeof_state,
1239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* slow,
1240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                  Label* done) {
124159151504615d929945dc59db37bf1166937748c6Steve Block  // Generate fast-case code for variables that might be shadowed by
124259151504615d929945dc59db37bf1166937748c6Steve Block  // eval-introduced variables.  Eval is used a lot without
124359151504615d929945dc59db37bf1166937748c6Steve Block  // introducing variables.  In those cases, we do not want to
124459151504615d929945dc59db37bf1166937748c6Steve Block  // perform a runtime call for all variables in the scope
124559151504615d929945dc59db37bf1166937748c6Steve Block  // containing the eval.
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (var->mode() == DYNAMIC_GLOBAL) {
1247589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
124859151504615d929945dc59db37bf1166937748c6Steve Block    __ jmp(done);
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == DYNAMIC_LOCAL) {
1250589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Variable* local = var->local_if_not_shadowed();
1251589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (local->mode() == CONST ||
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        local->mode() == CONST_HARMONY ||
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        local->mode() == LET) {
1255589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ cmp(eax, isolate()->factory()->the_hole_value());
1256589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ j(not_equal, done);
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (local->mode() == CONST) {
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(eax, isolate()->factory()->undefined_value());
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {  // LET || CONST_HARMONY
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(Immediate(var->name()));
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kThrowReferenceError, 1);
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
126359151504615d929945dc59db37bf1166937748c6Steve Block    }
1264589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ jmp(done);
126559151504615d929945dc59db37bf1166937748c6Steve Block  }
126659151504615d929945dc59db37bf1166937748c6Steve Block}
126759151504615d929945dc59db37bf1166937748c6Steve Block
126859151504615d929945dc59db37bf1166937748c6Steve Block
12693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
12703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Record position before possible IC call.
12713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SetSourcePosition(proxy->position());
12723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Variable* var = proxy->var();
12733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1274589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Three cases: global variables, lookup variables, and all other types of
1275589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // variables.
1276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  switch (var->location()) {
1277589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::UNALLOCATED: {
1278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "Global variable");
1279589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Use inline caching. Variable name is passed in ecx and the global
1280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // object in eax.
1281589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(eax, GlobalObjectOperand());
1282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(ecx, var->name());
1283589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1285589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      context()->Plug(eax);
1286589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1287589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
128859151504615d929945dc59db37bf1166937748c6Steve Block
1289589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::PARAMETER:
1290589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOCAL:
1291589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::CONTEXT: {
1292589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, var->IsContextSlot()
1293589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                              ? "Context variable"
1294589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                              : "Stack variable");
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->binding_needs_init()) {
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // var->scope() may be NULL when the proxy is located in eval code and
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // refers to a potential outside binding. Currently those bindings are
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always looked up dynamically, i.e. in that case
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     var->location() == LOOKUP.
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // always holds.
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(var->scope() != NULL);
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Check if the binding really needs an initialization check. The check
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // can be skipped in the following situation: we have a LET or CONST
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding in harmony mode, both the Variable and the VariableProxy have
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the same declaration scope (i.e. they are both in global code, in the
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // same function or in the same eval code) and the VariableProxy is in
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the source physically located after the initializer of the variable.
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We cannot skip any initialization checks for CONST in non-harmony
13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // mode because const variables may be declared but never initialized:
13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   if (false) { const x; }; var y = x;
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The condition on the declaration scopes is a conservative check for
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // nested functions that access a binding and are called before the
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // binding is initialized:
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   function() { f(); let x = 1; function f() { x = 2; } }
13183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bool skip_init_check;
13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          skip_init_check = false;
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
13233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Check that we always have valid source position.
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ASSERT(proxy->position() != RelocInfo::kNoPosition);
13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          skip_init_check = var->mode() != CONST &&
13273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              var->initializer_position() < proxy->position();
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!skip_init_check) {
13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Let and const need a read barrier.
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Label done;
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          GetVar(eax, var);
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ cmp(eax, isolate()->factory()->the_hole_value());
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ j(not_equal, &done, Label::kNear);
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (var->mode() == LET || var->mode() == CONST_HARMONY) {
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Throw a reference error when using an uninitialized let/const
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // binding in harmony mode.
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ push(Immediate(var->name()));
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ CallRuntime(Runtime::kThrowReferenceError, 1);
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Uninitalized const bindings outside of harmony mode are unholed.
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ASSERT(var->mode() == CONST);
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ mov(eax, isolate()->factory()->undefined_value());
13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ bind(&done);
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          context()->Plug(eax);
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          break;
1349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
1350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      context()->Plug(var);
1352589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
1354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case Variable::LOOKUP: {
1356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label done, slow;
1357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed
1358589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // by eval-introduced variables.
1359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&slow);
1361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Comment cmnt(masm_, "Lookup variable");
1362589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(esi);  // Context.
136369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ push(Immediate(var->name()));
1364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kLoadContextSlot, 2);
136569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ bind(&done);
136669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      context()->Plug(eax);
1367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      break;
1368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
13703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
13713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1373d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ RegExpLiteral");
1375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label materialized;
13763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Registers will be used as follows:
13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // edi = JS function.
1378bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // ecx = literals array.
1379bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // ebx = regexp literal.
1380bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // eax = regexp literal clone.
13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1382bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
13833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int literal_offset =
138480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1385bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ebx, FieldOperand(ecx, literal_offset));
138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(ebx, isolate()->factory()->undefined_value());
1387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &materialized, Label::kNear);
1388bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
13893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Create regexp literal using runtime function
13903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Result will be in eax.
1391bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(ecx);
13923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
13933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(expr->pattern()));
13943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(expr->flags()));
13953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1396bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(ebx, eax);
1397bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1398bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&materialized);
1399bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1400bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label allocated, runtime_allocate;
1401bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
1402bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&allocated);
1403bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1404bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&runtime_allocate);
1405bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(ebx);
1406bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(Immediate(Smi::FromInt(size)));
1407bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1408bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(ebx);
1409bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1410bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&allocated);
1411bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Copy the content into the newly allocated memory.
1412bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // (Unroll copy loop once for better throughput).
1413bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1414bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(edx, FieldOperand(ebx, i));
1415bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
1416bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, i), edx);
1417bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, i + kPointerSize), ecx);
1418bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
1419bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if ((size % (2 * kPointerSize)) != 0) {
1420bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(edx, FieldOperand(ebx, size - kPointerSize));
1421bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ mov(FieldOperand(eax, size - kPointerSize), edx);
1422bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
14230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) {
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expression == NULL) {
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(Immediate(isolate()->factory()->null_value()));
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(expression);
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1436d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ ObjectLiteral");
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_properties = expr->constant_properties();
1439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(Immediate(constant_properties));
144344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int flags = expr->fast_elements()
144444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kFastElements
144544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
144644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  flags |= expr->has_function()
144744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? ObjectLiteral::kHasFunction
144844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : ObjectLiteral::kNoFlags;
144944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ push(Immediate(Smi::FromInt(flags)));
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int properties_count = constant_properties->length() / 2;
1451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->depth() > 1) {
14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (flags != ObjectLiteral::kFastElements ||
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
145585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowObjectStub stub(properties_count);
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If result_saved is true the result is on top of the stack.  If
1462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // result_saved is false the result is in eax.
1463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool result_saved = false;
1464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
14653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Mark all computed expressions that are bound to a key that
14663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // is shadowed by a later occurrence of the same key. For the
14673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // marked expressions, no store code is emitted.
14683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  expr->CalculateEmitStore();
14693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AccessorTable accessor_table(isolate()->zone());
1471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < expr->properties()->length(); i++) {
1472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectLiteral::Property* property = expr->properties()->at(i);
1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (property->IsCompileTimeValue()) continue;
1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Literal* key = property->key();
1476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Expression* value = property->value();
1477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!result_saved) {
1478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ push(eax);  // Save result on the stack
1479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      result_saved = true;
1480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (property->kind()) {
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case ObjectLiteral::Property::CONSTANT:
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
1484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::COMPUTED:
1488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (key->handle()->IsSymbol()) {
14893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          if (property->emit_store()) {
1490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForAccumulatorValue(value);
1491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            __ mov(ecx, Immediate(key->handle()));
1492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            __ mov(edx, Operand(esp, 0));
14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<Code> ic = is_classic_mode()
14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                ? isolate()->builtins()->StoreIC_Initialize()
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                : isolate()->builtins()->StoreIC_Initialize_Strict();
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            CallIC(ic, RelocInfo::CODE_TARGET, key->id());
1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            PrepareForBailoutForId(key->id(), NO_REGISTERS);
1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else {
1499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            VisitForEffect(value);
15003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          }
1501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Fall through.
1504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case ObjectLiteral::Property::PROTOTYPE:
1505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ push(Operand(esp, 0));  // Duplicate receiver.
15060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(key);
15070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(value);
15083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (property->emit_store()) {
1509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(Smi::FromInt(NONE)));  // PropertyAttributes
1510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kSetProperty, 4);
15113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        } else {
15123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          __ Drop(3);
15133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        }
15145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        break;
151585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      case ObjectLiteral::Property::GETTER:
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->getter = value;
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case ObjectLiteral::Property::SETTER:
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accessor_table.lookup(key)->second->setter = value;
1520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Emit code to define accessors, using only a single call to the runtime for
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // each pair of corresponding getters and setters.
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (AccessorTable::Iterator it = accessor_table.begin();
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       it != accessor_table.end();
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       ++it) {
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(Operand(esp, 0));  // Duplicate receiver.
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(it->first);
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->getter);
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitAccessor(it->second->setter);
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(Immediate(Smi::FromInt(NONE)));
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
153744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (expr->has_function()) {
153844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(result_saved);
153944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ push(Operand(esp, 0));
154044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
154144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
154244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
15440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
15460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
15473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
15523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ ArrayLiteral");
1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ZoneList<Expression*>* subexprs = expr->values();
1555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int length = subexprs->length();
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> constant_elements = expr->constant_elements();
15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(2, constant_elements->length());
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind constant_elements_kind =
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_constant_fast_elements = constant_elements_kind == FAST_ELEMENTS;
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> constant_elements_values(
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FixedArrayBase::cast(constant_elements->get(1)));
1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
15663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ push(Immediate(Smi::FromInt(expr->literal_index())));
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(Immediate(constant_elements));
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap* heap = isolate()->heap();
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (has_constant_fast_elements &&
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      constant_elements_values->map() == heap->fixed_cow_array_map()) {
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the elements are already FAST_ELEMENTS, the boilerplate cannot
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // change, so it's possible to specialize the stub in advance.
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1);
1574756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    FastCloneShallowArrayStub stub(
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS,
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        length);
1577756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CallStub(&stub);
1578756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (expr->depth() > 1) {
1579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1580756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(constant_elements_kind == FAST_ELEMENTS ||
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FLAG_smi_only_arrays);
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the elements are already FAST_ELEMENTS, the boilerplate cannot
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // change, so it's possible to specialize the stub in advance.
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub::Mode mode = has_constant_fast_elements
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? FastCloneShallowArrayStub::CLONE_ELEMENTS
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FastCloneShallowArrayStub stub(mode, length);
1592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
15933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
15943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  bool result_saved = false;  // Is the result saved to the stack?
15963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
15973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Emit code to evaluate all the non-constant subexpressions and to store
15983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // them into the newly cloned array.
1599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  for (int i = 0; i < length; i++) {
16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Expression* subexpr = subexprs->at(i);
16013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // If the subexpression is a literal or a simple materialized literal it
16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // is already set in the cloned array.
16033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (subexpr->AsLiteral() != NULL ||
16043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        CompileTimeValue::IsCompileTimeValue(subexpr)) {
16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue;
16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (!result_saved) {
16093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(eax);
16103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      result_saved = true;
16113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
16120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(subexpr);
16133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_elements_kind == FAST_ELEMENTS) {
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Fast-case array literal with ElementsKind of FAST_ELEMENTS, they cannot
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // transition and don't need to call the runtime stub.
16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, Operand(esp, 0));  // Copy of array literal.
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the subexpression value in the array's elements.
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(FieldOperand(ebx, offset), result_register());
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the array store.
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(ebx, offset, result_register(), ecx,
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kDontSaveFPRegs,
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET,
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          INLINE_SMI_CHECK);
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the subexpression value in the array's elements.
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, Operand(esp, 0));  // Copy of array literal.
16303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(edi, FieldOperand(ebx, JSObject::kMapOffset));
16313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ecx, Immediate(Smi::FromInt(i)));
16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(edx, Immediate(Smi::FromInt(expr->literal_index())));
16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      StoreArrayLiteralElementStub stub;
16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallStub(&stub);
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
16383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (result_saved) {
16410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->PlugTOS();
1642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
16430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
16443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
16453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
16463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
16473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
1649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Comment cmnt(masm_, "[ Assignment");
1650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // on the left-hand side.
1652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->target()->IsValidLeftHandSide()) {
16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForEffect(expr->target());
1654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Left-hand side can only be a property, a global or a (parameter or local)
16583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
1659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1660402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  LhsKind assign_type = VARIABLE;
166180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Property* property = expr->target()->AsProperty();
166280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (property != NULL) {
166380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    assign_type = (property->key()->IsPropertyName())
166480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? NAMED_PROPERTY
166580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : KEYED_PROPERTY;
1666402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1667402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Evaluate LHS expression.
1669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1670402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1671402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Nothing to do here.
1672402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1673402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1674402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
1675402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        // We need the receiver both on the stack and in the accumulator.
16760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForAccumulatorValue(property->obj());
1677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(result_register());
1678402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
16790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForStackValue(property->obj());
1680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1681402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case KEYED_PROPERTY: {
1683402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (expr->is_compound()) {
16843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
16853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForAccumulatorValue(property->key());
1686402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ mov(edx, Operand(esp, 0));
1687402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ push(eax);
1688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
16893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->obj());
16903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        VisitForStackValue(property->key());
1691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1694402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
16968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For compound assignments we need another deoptimization point after the
16978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // variable/property load.
1698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (expr->is_compound()) {
169969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    AccumulatorValueContext result_context(this);
170069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    { AccumulatorValueContext left_operand_context(this);
17010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
17020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
17033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          EmitVariableLoad(expr->target()->AsVariableProxy());
17048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailout(expr->target(), TOS_REG);
17050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
17060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
17070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitNamedPropertyLoad(property);
17088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
17090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
17100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
17110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitKeyedPropertyLoad(property);
17128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
17130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
17140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
1715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
171780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Token::Value op = expr->binary_op();
1718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(eax);  // Left operand goes on the stack.
1719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    VisitForAccumulatorValue(expr->value());
1720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
172180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
172280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        ? OVERWRITE_RIGHT
172380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        : NO_OVERWRITE;
172480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetSourcePosition(expr->position() + 1);
172580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (ShouldInlineSmiCase(op)) {
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitInlineSmiBinaryOp(expr->binary_operation(),
172780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            op,
172880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            mode,
172980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                            expr->target(),
1730e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            expr->value());
173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    } else {
1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitBinaryOp(expr->binary_operation(), op, mode);
173380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Deoptimization point in case the binary operation may have side effects.
1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr->binary_operation(), TOS_REG);
173780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
17380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->value());
1739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1741402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Record source position before possible IC call.
1742402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  SetSourcePosition(expr->position());
1743402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1744402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Store the value.
1745402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  switch (assign_type) {
1746402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case VARIABLE:
1747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
17480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             expr->op());
1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->Plug(eax);
1751402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1752402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case NAMED_PROPERTY:
1753402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitNamedPropertyAssignment(expr);
1754402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1755402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    case KEYED_PROPERTY:
1756402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      EmitKeyedPropertyAssignment(expr);
1757402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      break;
1758402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1759402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1760402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1761402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1762d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
1764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Literal* key = prop->key()->AsLiteral();
1765053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  ASSERT(!key->handle()->IsSmi());
1766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(ecx, Immediate(key->handle()));
176744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, prop->id());
1769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1772d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(prop->position());
177444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, prop->id());
1776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Token::Value op,
178180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              OverwriteMode mode,
178280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                              Expression* left,
1783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              Expression* right) {
178480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do combined smi check of the operands. Left operand is on the
178580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stack. Right operand is in eax.
1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label smi_case, done, stub_call;
178780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ pop(edx);
178880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(ecx, eax);
17893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ or_(eax, edx);
1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  JumpPatchSite patch_site(masm_);
1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
179280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
179380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&stub_call);
1794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(eax, ecx);
1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(op, mode);
17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
17973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&done, Label::kNear);
179980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Smi case.
180180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&smi_case);
180280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(eax, edx);  // Copy left operand in case of a stub call.
180380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
180480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
180580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR:
180680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
180780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
180880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ sar_cl(eax);  // No checks of result necessary
180980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
181080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
181180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL: {
181280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label result_ok;
181380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
181480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
181580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ shl_cl(eax);
181680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Check that the *signed* result fits in a smi.
181780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ cmp(eax, 0xc0000000);
181880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(positive, &result_ok);
181980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(ecx);
182080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(&stub_call);
182180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&result_ok);
182280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
182380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
182480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
182580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR: {
182680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label result_ok;
182780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
182880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(ecx);
182980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ shr_cl(eax);
183080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ test(eax, Immediate(0xc0000000));
183180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(zero, &result_ok);
183280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(ecx);
183380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ jmp(&stub_call);
183480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&result_ok);
183580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiTag(eax);
183680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
183780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
183880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
18393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(eax, ecx);
184080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
184180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
184280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sub(eax, ecx);
184480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
184580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
184680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MUL: {
184780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ SmiUntag(eax);
18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ imul(eax, ecx);
184980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(overflow, &stub_call);
18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ test(eax, eax);
1851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ j(not_zero, &done, Label::kNear);
185280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ mov(ebx, edx);
18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ or_(ebx, ecx);
185480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(negative, &stub_call);
185580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
185680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
185780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ or_(eax, ecx);
185980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
186080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ and_(eax, ecx);
186280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
186380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ xor_(eax, ecx);
186580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
186680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
186780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
186880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
186980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
187080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
18710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
187280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
187380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
187480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
1876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Token::Value op,
187780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                     OverwriteMode mode) {
1878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ pop(edx);
1879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(op, mode);
18803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
18823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
18830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
1884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) {
1888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw
1889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ReferenceError' on the left-hand side.
1890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->IsValidLeftHandSide()) {
18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForEffect(expr);
1892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
1893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Left-hand side can only be a property, a global or a (parameter or local)
18963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
1897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  LhsKind assign_type = VARIABLE;
1899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Property* prop = expr->AsProperty();
1900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (prop != NULL) {
1901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    assign_type = (prop->key()->IsPropertyName())
1902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        ? NAMED_PROPERTY
1903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        : KEYED_PROPERTY;
1904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  switch (assign_type) {
1907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case VARIABLE: {
1908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Variable* var = expr->AsVariableProxy()->var();
19090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EffectContext context(this);
19100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      EmitVariableAssignment(var, Token::ASSIGN);
1911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case NAMED_PROPERTY: {
1914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(eax);  // Preserve value.
19150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
1916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(edx, eax);
1917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(eax);  // Restore value.
1918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ mov(ecx, prop->key()->AsLiteral()->handle());
19193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
19203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->StoreIC_Initialize()
19213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->StoreIC_Initialize_Strict();
19223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic);
1923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case KEYED_PROPERTY: {
1926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ push(eax);  // Preserve value.
192769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      VisitForStackValue(prop->obj());
192869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      VisitForAccumulatorValue(prop->key());
192969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(ecx, eax);
193069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ pop(edx);
1931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      __ pop(eax);  // Restore value.
19323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
19333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->KeyedStoreIC_Initialize()
19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
19353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic);
1936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
1937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(eax);
1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1943d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
19440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               Token::Value op) {
1945589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (var->IsUnallocated()) {
1946589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Global var, const, or let.
19473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ mov(ecx, var->name());
19488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(edx, GlobalObjectOperand());
19493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic = is_classic_mode()
19503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? isolate()->builtins()->StoreIC_Initialize()
19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : isolate()->builtins()->StoreIC_Initialize_Strict();
19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
19541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (op == Token::INIT_CONST) {
1955589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Const initializers need a write barrier.
1956589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ASSERT(!var->IsParameter());  // No const parameters.
1957589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsStackLocal()) {
1958589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label skip;
1959589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(edx, StackOperand(var));
1960589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ cmp(edx, isolate()->factory()->the_hole_value());
1961589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ j(not_equal, &skip);
1962589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(StackOperand(var), eax);
1963589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&skip);
1964589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
1965589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsContextSlot() || var->IsLookupSlot());
1966589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Like var declarations, const declarations are hoisted to function
1967589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // scope.  However, unlike var initializers, const initializers are
1968589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // able to drill a hole to that function context, even from inside a
1969589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // 'with' context.  We thus bypass the normal static scope lookup for
1970589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // var->IsContextSlot().
1971589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(eax);
1972589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(esi);
1973589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(Immediate(var->name()));
1974589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
19751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
19761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
19773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (var->mode() == LET && op != Token::INIT_LET) {
1978589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Non-initializing assignment to let variable needs a write barrier.
1979589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsLookupSlot()) {
1980589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(eax);  // Value.
1981589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(esi);  // Context.
1982589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(Immediate(var->name()));
19833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(Immediate(Smi::FromInt(language_mode())));
1984589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kStoreContextSlot, 4);
1985589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
1986589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsStackAllocated() || var->IsContextSlot());
1987589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Label assign;
1988589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      MemOperand location = VarOperand(var, ecx);
1989589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(edx, location);
1990589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ cmp(edx, isolate()->factory()->the_hole_value());
1991589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ j(not_equal, &assign, Label::kNear);
1992589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(Immediate(var->name()));
1993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kThrowReferenceError, 1);
1994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ bind(&assign);
1995589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(location, eax);
1996589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
199769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ mov(edx, eax);
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int offset = Context::SlotOffset(var->index());
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
200069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
200169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
2002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assignment to var or initializing assignment to let/const
20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // in harmony mode.
2006589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (var->IsStackAllocated() || var->IsContextSlot()) {
2007589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      MemOperand location = VarOperand(var, ecx);
2008589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (FLAG_debug_code && op == Token::INIT_LET) {
2009589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // Check for an uninitialized let binding.
2010589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ mov(edx, location);
2011589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ cmp(edx, isolate()->factory()->the_hole_value());
2012589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        __ Check(equal, "Let binding re-initialization.");
2013589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      }
2014589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Perform the assignment.
2015589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ mov(location, eax);
2016589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (var->IsContextSlot()) {
2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        __ mov(edx, eax);
20183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int offset = Context::SlotOffset(var->index());
20193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
20203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
2021589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
2022589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT(var->IsLookupSlot());
2023589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(eax);  // Value.
2024589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(esi);  // Context.
2025589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ push(Immediate(var->name()));
20263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(Immediate(Smi::FromInt(language_mode())));
2027589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ CallRuntime(Runtime::kStoreContextSlot, 4);
20283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
20293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2030589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Non-initializing assignments to consts are ignored.
20313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
20323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
20333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a named store IC.
2036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Property* prop = expr->target()->AsProperty();
2037d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop != NULL);
2038d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(prop->key()->AsLiteral() != NULL);
20393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
2041d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
2042d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
2043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
2044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
2045e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(Operand(esp, kPointerSize));  // Receiver is now under value.
2046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
2047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
2048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2050e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2051e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
2052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(ecx, prop->key()->AsLiteral()->handle());
20534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (expr->ends_initialization_block()) {
20544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ mov(edx, Operand(esp, 0));
20554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
20564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ pop(edx);
20574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = is_classic_mode()
20593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->StoreIC_Initialize()
20603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->StoreIC_Initialize_Strict();
20613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
2064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
2065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(eax);  // Result of assignment, saved even if not needed.
2066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(esp, kPointerSize));  // Receiver is under value.
2067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
2068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(eax);
2069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ Drop(1);
2070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(eax);
2073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2076d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Assignment to a property, using a keyed store IC.
2078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment starts a block of assignments to the same object,
2080d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // change to slow case to avoid the quadratic behavior of repeatedly
2081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // adding fast properties.
2082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->starts_initialization_block()) {
2083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(result_register());
2084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Receiver is now under the key and value.
2085d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(Operand(esp, 2 * kPointerSize));
2086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToSlowProperties, 1);
2087e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(result_register());
2088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2089d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
20906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(ecx);
20916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (expr->ends_initialization_block()) {
20926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(edx, Operand(esp, 0));  // Leave receiver on the stack for later.
20936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
20946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(edx);
20956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source code position before IC call.
2097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  SetSourcePosition(expr->position());
20983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic = is_classic_mode()
20993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? isolate()->builtins()->KeyedStoreIC_Initialize()
21003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
21013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the assignment ends an initialization block, revert to fast case.
2104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->ends_initialization_block()) {
21056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(edx);
2106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(eax);  // Result of assignment, saved even if not needed.
21076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ push(edx);
2108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(Runtime::kToFastProperties, 1);
2109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ pop(eax);
2110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
21130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2114d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) {
2118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Property");
2119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Expression* key = expr->key();
2120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (key->IsPropertyName()) {
21220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->obj());
2123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitNamedPropertyLoad(expr);
2124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(eax);
2125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
21260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(expr->obj());
21270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForAccumulatorValue(expr->key());
2128402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(edx);
2129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    EmitKeyedPropertyLoad(expr);
2130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->Plug(eax);
2131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
21353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::CallIC(Handle<Code> code,
21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               RelocInfo::Mode rmode,
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               unsigned ast_id) {
21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ic_total_count_++;
21393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ call(code, rmode, ast_id);
21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2145d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr,
2146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       Handle<Object> name,
2147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                       RelocInfo::Mode mode) {
2148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the IC.
2149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
21503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
2151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
21523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
21533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
21543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
21553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    __ Set(ecx, Immediate(name));
21563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Record source position of the IC call.
2158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
2159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic =
2160589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, mode, expr->id());
2162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
2163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Restore context register.
2164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
21650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
21697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Expression* key) {
21718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the key.
21728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(key);
21738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Swap the name of the function and the receiver on the stack to follow
21758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the calling convention for call ICs.
21768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(ecx);
21778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(eax);
21788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(ecx);
21798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the arguments.
21817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
21827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int arg_count = args->length();
2183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
21843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
21853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
21863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
21877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
21887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Record source position of the IC call.
2189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
2190589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Handle<Code> ic =
2191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
21928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize));  // Key.
21933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
2194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
21957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Restore context register.
21967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
21978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->DropAndPlug(1, eax);  // Drop the key still on the stack.
21987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
21997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
22007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Code common for calls using the call stub.
2203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  { PreservePositionScope scope(masm()->positions_recorder());
22063e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    for (int i = 0; i < arg_count; i++) {
22073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      VisitForStackValue(args->at(i));
22083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Record source position for debugger.
2211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record call targets in unoptimized code, but not in the snapshot.
22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!Serializer::enabled()) {
22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> uninitialized =
22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        TypeFeedbackCells::UninitializedSentinel(isolate());
22183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
22193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
22203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordTypeFeedbackCell(expr->id(), cell);
22213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, cell);
22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  CallFunctionStub stub(arg_count, flags);
22253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
22263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallStub(&stub, expr->id());
22273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RecordJSReturnSite(expr);
22293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Restore context register.
22303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
22310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->DropAndPlug(1, eax);
2232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push copy of the first argument or undefined if it doesn't exist.
2237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (arg_count > 0) {
2238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ push(Operand(esp, arg_count * kPointerSize));
2239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
224044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ push(Immediate(isolate()->factory()->undefined_value()));
2241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Push the receiver of the enclosing function.
22443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the language mode.
22463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(Immediate(Smi::FromInt(language_mode())));
2247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the start position of the scope the calls resides in.
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(Immediate(Smi::FromInt(scope()->start_position())));
2250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the runtime call.
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) {
2257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
2258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We want to verify that RecordJSReturnSite gets called on all paths
2259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // through this function.  Avoid early returns.
2260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  expr->return_is_recorded_ = false;
2261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
2262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ Call");
2264589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Expression* callee = expr->expression();
2265589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  VariableProxy* proxy = callee->AsVariableProxy();
2266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Property* property = callee->AsProperty();
2267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2268589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL && proxy->var()->is_possibly_eval()) {
2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // In a call to eval, we first call %ResolvePossiblyDirectEval to
2270589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // resolve the function we need to call and the receiver of the call.
2271589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Then we call the resolved function using the given arguments.
2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ZoneList<Expression*>* args = expr->arguments();
2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int arg_count = args->length();
2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope pos_scope(masm()->positions_recorder());
2275589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
22763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Reserved receiver slot.
227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ push(Immediate(isolate()->factory()->undefined_value()));
22783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Push the arguments.
22793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      for (int i = 0; i < arg_count; i++) {
22803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VisitForStackValue(args->at(i));
22813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      }
2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2283589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Push a copy of the function (found below the arguments) and
2284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // resolve eval.
2285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      __ push(Operand(esp, (arg_count + 1) * kPointerSize));
22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      EmitResolvePossiblyDirectEval(arg_count);
2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
22883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // The runtime call returns a pair of values in eax (function) and
22893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // edx (receiver). Touch up the stack with the right values.
22903e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
22913e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
22923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Record source position for debugger.
2294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetSourcePosition(expr->position());
2295589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT);
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallStub(&stub);
2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    RecordJSReturnSite(expr);
2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Restore context register.
2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
23010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->DropAndPlug(1, eax);
2302589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2303589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
2304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Push global object as receiver for the call IC.
23058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(GlobalObjectOperand());
2306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
2307589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2308589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
230959151504615d929945dc59db37bf1166937748c6Steve Block    // Call to a lookup slot (dynamically introduced variable).
231059151504615d929945dc59db37bf1166937748c6Steve Block    Label slow, done;
2311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // Generate code for loading from variables potentially shadowed by
2313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // eval-introduced variables.
2314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
23153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
231659151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
2317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call the runtime to find the function to call (returned in eax) and
2318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // the object holding it (returned in edx).
2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(context_register());
2320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ push(Immediate(proxy->name()));
2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLoadContextSlot, 2);
2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(eax);  // Function.
2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ push(edx);  // Receiver.
232459151504615d929945dc59db37bf1166937748c6Steve Block
2325589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // If fast case code has been generated, emit code to push the function
2326589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // and receiver and have the slow path jump around this code.
232759151504615d929945dc59db37bf1166937748c6Steve Block    if (done.is_linked()) {
232859151504615d929945dc59db37bf1166937748c6Steve Block      Label call;
2329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      __ jmp(&call, Label::kNear);
233059151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&done);
23313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Push function.
233259151504615d929945dc59db37bf1166937748c6Steve Block      __ push(eax);
2333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // The receiver is implicitly the global receiver. Indicate this by
2334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // passing the hole to the call function stub.
23353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ push(Immediate(isolate()->factory()->the_hole_value()));
233659151504615d929945dc59db37bf1166937748c6Steve Block      __ bind(&call);
233759151504615d929945dc59db37bf1166937748c6Steve Block    }
233859151504615d929945dc59db37bf1166937748c6Steve Block
2339589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // The receiver is either the global receiver or an object found by
2340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // LoadContextSlot. That object could be the hole if the receiver is
2341589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // implicitly the global object.
2342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
2343589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (property != NULL) {
2345589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2346589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(property->obj());
2347589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
2348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (property->key()->IsPropertyName()) {
2349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitCallWithIC(expr,
2350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     property->key()->AsLiteral()->handle(),
2351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                     RelocInfo::CODE_TARGET);
2352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
2353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      EmitKeyedCallWithIC(expr, property->key());
2354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
23563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
2357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Call to an arbitrary expression not handled specially above.
2358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    { PreservePositionScope scope(masm()->positions_recorder());
2359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VisitForStackValue(callee);
23603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
2361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load global receiver object.
23628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(ebx, GlobalObjectOperand());
2363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Emit function call.
2365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
23663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
2369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // RecordJSReturnSite should have been called.
2370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr->return_is_recorded_);
2371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
23723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
23733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
23743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2375d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CallNew");
2377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // According to ECMA-262, section 11.2.2, page 44, the function
2378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // expression in new calls must be evaluated before the
2379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // arguments.
2380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
238180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push constructor on the stack.  If it's not a function it's used as
238280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
238380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ignored.
23840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->expression());
2385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Push the arguments ("left-to-right") on the stack.
2387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ZoneList<Expression*>* args = expr->arguments();
2388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int arg_count = args->length();
2389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < arg_count; i++) {
23900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
2391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call the construct call builtin that handles allocation and
2394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // constructor invocation.
2395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SetSourcePosition(expr->position());
2396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
239780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load function and argument count into edi and eax.
2398053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  __ SafeSet(eax, Immediate(arg_count));
239980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(edi, Operand(esp, arg_count * kPointerSize));
2400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record call targets in unoptimized code, but not in the snapshot.
24023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallFunctionFlags flags;
24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!Serializer::enabled()) {
24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    flags = RECORD_CALL_TARGET;
24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> uninitialized =
24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        TypeFeedbackCells::UninitializedSentinel(isolate());
24073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell =
24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
24093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordTypeFeedbackCell(expr->id(), cell);
24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, cell);
24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    flags = NO_CALL_FUNCTION_FLAGS;
24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallConstructStub stub(flags);
24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
24173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
24180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
243180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask));
243780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
24443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
245280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(eax, Immediate(kSmiTagMask | 0x80000000));
245880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
247380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
24740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
24750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, if_false);
247844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(eax, isolate()->factory()->null_value());
2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(equal, if_true);
2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Undetectable objects behave like undefined when tested with typeof.
2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
2483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_zero, if_false);
2485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
24863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, if_false);
24883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
24893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
249080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(below_equal, if_true, if_false, fall_through);
2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
24973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
24983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(args->length() == 1);
24993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
25013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label materialize_true, materialize_false;
25033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_true = NULL;
25043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label* if_false = NULL;
250580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
25083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, if_false);
25103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx);
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
251280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(above_equal, if_true, if_false, fall_through);
25133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
25153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
25163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
252780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, if_false);
2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ test(ebx, Immediate(1 << Map::kIsUndetectable));
25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
253680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(not_zero, if_true, if_false, fall_through);
2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
25380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2542756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
25433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallRuntime* expr) {
25443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2545756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(args->length() == 1);
2546756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
25470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2548756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2549756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label materialize_true, materialize_false;
2550756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_true = NULL;
2551756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Label* if_false = NULL;
255280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
25530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
25540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2555756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
25568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (FLAG_debug_code) __ AbortIfSmi(eax);
25578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
25588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Check whether this map has already been checked to be safe for default
25598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // valueOf.
25608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
25618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ test_b(FieldOperand(ebx, Map::kBitField2Offset),
25628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            1 << Map::kStringWrapperSafeForDefaultValueOf);
25638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(not_zero, if_true);
25648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
25658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Check for fast case object. Return false for slow case objects.
25668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(ecx, FieldOperand(eax, JSObject::kPropertiesOffset));
25678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
25688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(ecx, FACTORY->hash_table_map());
25698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(equal, if_false);
25708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
25718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Look for valueOf symbol in the descriptor array, and indicate false if
25728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // found. The type is not checked, so if it is a transition it is a false
25738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // negative.
2574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadInstanceDescriptors(ebx, ebx);
25758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
25768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // ebx: descriptor array
25778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // ecx: length of descriptor array
25788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate the end of the descriptor array.
25798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
25808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  STATIC_ASSERT(kSmiTagSize == 1);
25818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  STATIC_ASSERT(kPointerSize == 4);
25828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ lea(ecx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
25838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Calculate location of the first key name.
25843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(ebx,
25853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Immediate(FixedArray::kHeaderSize +
25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   DescriptorArray::kFirstIndex * kPointerSize));
25878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Loop through all the keys in the descriptor array. If one of these is the
25888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // symbol valueOf the result is false.
25898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Label entry, loop;
25908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ jmp(&entry);
25918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&loop);
25928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(edx, FieldOperand(ebx, 0));
25938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(edx, FACTORY->value_of_symbol());
25948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(equal, if_false);
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(ebx, Immediate(kPointerSize));
25968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ bind(&entry);
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(ebx, ecx);
25988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(not_equal, &loop);
25998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Reload map as register ebx was used as temporary above.
26018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
26028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // If a valueOf property is not found on the object check that it's
26048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // prototype is the un-modified String prototype. If not result is false.
26058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
26063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(ecx, if_false);
26078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
26088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
26098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(edx,
26108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         FieldOperand(edx, GlobalObject::kGlobalContextOffset));
26118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ cmp(ecx,
26128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         ContextOperand(edx,
26138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                        Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
26148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ j(not_equal, if_false);
26158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Set the bit in the map to indicate that it has been checked safe for
26168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // default valueOf and set true result.
26178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ or_(FieldOperand(ebx, Map::kBitField2Offset),
26188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
26198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ jmp(if_true);
26208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
26213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
26220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2625756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
26263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
263580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
26360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, if_false);
2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
264280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
265780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
26580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, if_false);
2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
266480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
267980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
26800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
26810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, if_false);
2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
268680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
26933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
269980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
27000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
27010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the frame pointer for the calling frame.
2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Skip the arguments adaptor frame if it exists.
2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label check_frame_marker;
2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(eax, StandardFrameConstants::kContextOffset),
2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &check_frame_marker);
2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset));
2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check the marker in the calling frame.
2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&check_frame_marker);
2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
271880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
2727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the two objects into registers and perform the comparison.
27290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
27300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
2731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
2733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
2734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
273580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
27360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
27370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
2738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(ebx);
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, ebx);
27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
274280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(equal, if_true, if_false, fall_through);
2743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
2745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) {
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ArgumentsAccessStub expects the key in edx and the formal
2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // parameter count in eax.
27540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, eax);
27563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
27590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label exit;
2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Get the number of formal parameters.
27683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check if the calling frame is an arguments adaptor frame.
2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &exit);
2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Arguments adaptor case: Read the arguments length from the
2777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // adaptor frame.
2778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&exit);
2781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (FLAG_debug_code) __ AbortIfNotSmi(eax);
27820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, null, function, non_function_constructor;
2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
27910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, we return null.
27943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &null);
2795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Check that the object is a JS object but take special care of JS
2797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // functions to make sure they have 'Function' as their class.
27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there are only two callable types, and one of them is at
27993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // either end of the type range for JS object types. Saves extra comparisons.
28003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
28013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, eax);
28023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Map is now in eax.
2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(below, &null);
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                FIRST_SPEC_OBJECT_TYPE + 1);
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &function);
28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpInstanceType(eax, LAST_SPEC_OBJECT_TYPE);
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                LAST_SPEC_OBJECT_TYPE - 1);
28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &function);
28123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assume that there is no larger type.
28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a JS function.
2816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, Map::kConstructorOffset));
2817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &non_function_constructor);
2819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // eax now contains the constructor function. Grab the
2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // instance class name from there.
2822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
2823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
2824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Functions have class 'Function'.
2827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&function);
282844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, isolate()->factory()->function_class_symbol());
2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Objects with a non-function constructor have class 'Object'.
2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&non_function_constructor);
283344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, isolate()->factory()->Object_symbol());
2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Non-JS objects have class null.
2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&null);
283844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, isolate()->factory()->null_value());
2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // All done.
2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLog(CallRuntime* expr) {
2848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Conditionally generate a log call.
2849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Args:
2850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   0 (literal string): The type of logging (corresponds to the flags).
2851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     This is used to determine whether or not to generate the log call.
2852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   1 (string): Format string.  Access the string at argument index 2
2853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //     with '%2s' (see Logger::LogRuntime for all the formats).
2854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   2 (array): Arguments to the format string.
28553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 3);
2857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
28580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(1));
28590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(2));
2860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ CallRuntime(Runtime::kLog, 2);
2861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Finally, we're expected to leave a value on the top of the stack.
286344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, isolate()->factory()->undefined_value());
28640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(expr->arguments()->length() == 0);
2870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label slow_allocate_heapnumber;
2872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label heapnumber_allocated;
2873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber);
2875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&heapnumber_allocated);
2876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&slow_allocate_heapnumber);
28783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Allocate a heap number.
28793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CallRuntime(Runtime::kNumberAlloc, 0);
2880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edi, eax);
2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&heapnumber_allocated);
2883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
28848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ PrepareCallCFunction(1, ebx);
28853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(eax, ContextOperand(context_register(), Context::GLOBAL_INDEX));
28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(eax, FieldOperand(eax, GlobalObject::kGlobalContextOffset));
28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(Operand(esp, 0), eax);
28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
2889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Convert 32 random bits in eax to 0.(32 random bits) in a double
2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // by computing:
2892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // This is implemented on both SSE2 and FPU.
28948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(SSE2)) {
2895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope fscope(SSE2);
2896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movd(xmm1, ebx);
28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movd(xmm0, eax);
2899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ cvtss2sd(xmm1, xmm1);
2900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ xorps(xmm0, xmm1);
2901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ subsd(xmm0, xmm1);
2902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0);
2903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
2904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x4130000000000000 is 1.0 x 2^20 as a double.
2905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kExponentOffset),
2906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           Immediate(0x41300000));
2907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax);
2908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0));
2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fsubp(1);
2912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset));
2913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, edi);
29150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) {
2920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  SubStringStub stub;
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
29240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
29260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
2927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
2933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the stub.
2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RegExpExecStub stub;
29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 4);
29370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
29380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
29390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
29400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(3));
2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
29420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
29473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
2949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));  // Load the object.
2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
2953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi return the object.
29543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &done, Label::kNear);
2955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the object.
2956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
2957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &done, Label::kNear);
2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
2959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
29610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
2962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) {
29663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(args->length() == 2);
29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_NE(NULL, args->at(1)->AsLiteral());
29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle()));
29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(args->at(0));  // Load the object.
29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label runtime, done;
29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = eax;
29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = eax;
29763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = ecx;
29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
29793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AbortIfSmi(object);
29803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Assert(equal, "Trying to get date field from non-date.");
29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (index->value() == 0) {
29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(result, FieldOperand(object, JSDate::kValueOffset));
29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (index->value() < JSDate::kFirstUncachedField) {
29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(scratch, Operand::StaticVariable(stamp));
29903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &runtime, Label::kNear);
29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(result, FieldOperand(object, JSDate::kValueOffset +
29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          kPointerSize * index->value()));
29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&runtime);
29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ PrepareCallCFunction(2, scratch);
29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(Operand(esp, 0), object);
29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(result);
30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the arguments on the stack and call the runtime function.
30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
30110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(SSE2)) {
30153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MathPowStub stub(MathPowStub::ON_STACK);
301644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CallStub(&stub);
301744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
301844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CallRuntime(Runtime::kMath_pow, 2);
301944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
30200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 2);
3027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));  // Load the object.
30290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));  // Load the value.
3030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ pop(ebx);  // eax = value. ebx = object.
3031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
3033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is a smi, return the value.
30343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(ebx, &done, Label::kNear);
3035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the object is not a value type, return the value.
3037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
3038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &done, Label::kNear);
3039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store the value.
3041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Update the write barrier.  Save the value as it will be
3044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // overwritten by the write barrier code and is needed afterward.
3045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(edx, eax);
30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs);
3047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
30490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(args->length(), 1);
3056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
30580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  NumberToStringStub stub;
3061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
30620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
3071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
30737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharFromCodeGenerator generator(eax, ebx);
30747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
3075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
30787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
3079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
30810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(ebx);
3082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
30877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
30887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
30900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
30917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = ebx;
30937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = eax;
30947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = edx;
30957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
30977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
30997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
31007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
31017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharCodeAtGenerator generator(object,
31027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      index,
31037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      result,
31047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
31057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &need_conversion,
31067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      &index_out_of_range,
31077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      STRING_INDEX_IS_NUMBER);
31087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
31097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
31127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
31137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // NaN.
311444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(result, Immediate(isolate()->factory()->nan_value()));
31157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
3118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Move the undefined value into the result register, which will
31197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // trigger conversion.
312044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(result, Immediate(isolate()->factory()->undefined_value()));
31217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
31247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
31257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
31270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
3128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
31337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(args->length() == 2);
31347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
31360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
31377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register object = ebx;
31397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = eax;
31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = edx;
31417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
31427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(object);
31447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label need_conversion;
31467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
31477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label done;
31487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator generator(object,
31497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  index,
31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
31517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  result,
31527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
31537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &need_conversion,
31547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  &index_out_of_range,
31557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  STRING_INDEX_IS_NUMBER);
31567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateFast(masm_);
31577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_out_of_range);
31607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // When the index is out of range, the spec requires us to return
31617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the empty string.
316244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Set(result, Immediate(isolate()->factory()->empty_string()));
31637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&need_conversion);
31667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Move smi zero into the result register, which will trigger
31677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // conversion.
31687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(result, Immediate(Smi::FromInt(0)));
31697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&done);
31707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  NopRuntimeCallHelper call_helper;
31727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  generator.GenerateSlow(masm_, call_helper);
31737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&done);
31750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result);
31767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
31777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
31803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
3182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
31840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringAddStub stub(NO_STRING_ADD_FLAGS);
3187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
31880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
31933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
3195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
31960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
31970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
3198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  StringCompareStub stub;
3200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
32010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
3206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
3207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranscendentalCacheStub stub(TranscendentalCache::SIN,
3208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               TranscendentalCacheStub::TAGGED);
32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
32110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
32130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the stub.
3219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranscendentalCacheStub stub(TranscendentalCache::COS,
3220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               TranscendentalCacheStub::TAGGED);
32213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
32223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(args->length() == 1);
32233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForStackValue(args->at(0));
32243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallStub(&stub);
32253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(eax);
32263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathTan(CallRuntime* expr) {
32303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the argument on the stack and call the stub.
32313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TranscendentalCacheStub stub(TranscendentalCache::TAN,
32323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               TranscendentalCacheStub::TAGGED);
32333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(args->length() == 1);
3235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitForStackValue(args->at(0));
3236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
3237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->Plug(eax);
3238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
32413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
3242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the argument on the stack and call the stub.
3243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranscendentalCacheStub stub(TranscendentalCache::LOG,
3244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               TranscendentalCacheStub::TAGGED);
32453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
32470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallStub(&stub);
32490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
3254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load the argument on the stack and call the runtime function.
32553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 1);
32570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
3258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kMath_sqrt, 1);
32590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
32643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() >= 2);
3266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < arg_count + 1; ++i) {
3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitForStackValue(args->at(i));
3270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VisitForAccumulatorValue(args->last());  // Function.
3272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for proxy.
32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label proxy, done;
32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(eax, JS_FUNCTION_PROXY_TYPE, ebx);
32763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &proxy);
32773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // InvokeFunction requires the function in edi. Move it in there.
3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(edi, result_register());
3280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ParameterCount count(arg_count);
3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi, count, CALL_FUNCTION,
3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
3283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
32843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
32853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&proxy);
32873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(eax);
32883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kCall, args->length());
32893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Load the arguments on the stack and call the stub.
3297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RegExpConstructResultStub stub;
32983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(args->length() == 3);
33000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
33010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(1));
33020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(2));
3303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallStub(&stub);
33040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
33093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(2, args->length());
3311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_NE(NULL, args->at(0)->AsLiteral());
3313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<FixedArray> jsfunction_result_caches(
331644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->global_context()->jsfunction_result_caches());
3317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (jsfunction_result_caches->length() <= cache_id) {
3318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ Abort("Attempt to use undefined cache.");
331944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ mov(eax, isolate()->factory()->undefined_value());
33200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
3321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register key = eax;
3327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register cache = ebx;
3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register tmp = ecx;
332959151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(cache, ContextOperand(esi, Context::GLOBAL_INDEX));
3330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
3331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldOperand(cache, GlobalObject::kGlobalContextOffset));
333259151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(cache,
3334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label done, not_found;
3337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // tmp now holds finger offset as a smi.
333869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
3341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ j(not_equal, &not_found);
3342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1));
3344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ jmp(&done);
3345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&not_found);
3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Call runtime to perform the lookup.
3348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(cache);
3349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ push(key);
3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ CallRuntime(Runtime::kGetFromCache, 2);
3351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ bind(&done);
33530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
3355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
3359bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(2, args->length());
3360bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3361bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register right = eax;
3362bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register left = ebx;
3363bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = ecx;
3364bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
33650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(args->at(0));
33660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(1));
3367bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ pop(left);
3368bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3369bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label done, fail, ok;
33703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(left, right);
3371bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
3372bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Fail if either is a non-HeapObject.
3373bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(tmp, left);
33743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(tmp, right);
33753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(tmp, &fail);
337644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset));
337744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CmpInstanceType(tmp, JS_REGEXP_TYPE);
3378bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
3379bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset));
3380bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(not_equal, &fail);
3381bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3382bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3383bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ j(equal, &ok);
3384bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&fail);
338544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, Immediate(isolate()->factory()->false_value()));
3386bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ jmp(&done);
3387bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&ok);
338844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, Immediate(isolate()->factory()->true_value()));
3389bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&done);
3390bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
33910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3392bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
3393bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
3394bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
339780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
339880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
33990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
340080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
340180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (FLAG_debug_code) {
340280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ AbortIfNotString(eax);
340380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
340480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
340580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
340680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
340780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
340880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
34090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
34100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
341180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
341280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ test(FieldOperand(eax, String::kHashFieldOffset),
341380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Immediate(String::kContainsCachedArrayIndexMask));
34143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
341580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Split(zero, if_true, if_false, fall_through);
341680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
341880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
341980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
342080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
34223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
342380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(args->length() == 1);
34240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(args->at(0));
342580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
342680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (FLAG_debug_code) {
342780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ AbortIfNotString(eax);
342880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
342980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
343080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
343180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(eax, eax);
343280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
343480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
343580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
343680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
34373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3438b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label bailout, done, one_char_separator, long_separator,
3439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      non_trivial_array, not_size_one_array, loop,
3440b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
34418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
34423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
34438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(args->length() == 2);
34448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We will leave the separator on the stack until the end of the function.
34458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForStackValue(args->at(1));
34468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load this to eax (= array)
34478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  VisitForAccumulatorValue(args->at(0));
34488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // All aliases of the same register have disjoint lifetimes.
34498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register array = eax;
3450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register elements = no_reg;  // Will be eax.
34518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register index = edx;
34538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register string_length = ecx;
34558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register string = esi;
34578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
34588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register scratch = ebx;
34598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register array_length = edi;
3461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Register result_pos = no_reg;  // Will be edi.
34628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Separator operand is already pushed.
3464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Operand separator_operand = Operand(esp, 2 * kPointerSize);
3465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Operand result_operand = Operand(esp, 1 * kPointerSize);
3466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Operand array_length_operand = Operand(esp, 0);
34673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(esp, Immediate(2 * kPointerSize));
3468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cld();
3469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check that the array is a JSArray
34703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(array, &bailout);
34718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
34728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
34738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
34748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that the array has fast elements.
34753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckFastElements(scratch, &bailout);
34768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3477b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // If the array has length zero, return the empty string.
3478b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
3479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ SmiUntag(array_length);
3480b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(not_zero, &non_trivial_array);
348144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(result_operand, isolate()->factory()->empty_string());
34828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ jmp(&done);
34838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3484b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Save the array length.
3485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&non_trivial_array);
3486b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(array_length_operand, array_length);
34878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Save the FixedArray containing array's elements.
34898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // End of array's live range.
3490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  elements = array;
3491b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(elements, FieldOperand(array, JSArray::kElementsOffset));
34928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  array = no_reg;
34938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
34948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3495b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check that all array elements are sequential ASCII strings, and
3496b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // accumulate the sum of their lengths, as a smi-encoded value.
3497b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ Set(index, Immediate(0));
3498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ Set(string_length, Immediate(0));
3499b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Loop condition: while (index < length).
3500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live loop registers: index, array_length, string,
3501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //                      scratch, string_length, elements.
3502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_debug_code) {
35033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(index, array_length);
3504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin");
3505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
3506b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop);
3507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(string, FieldOperand(elements,
3508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              index,
3509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              times_pointer_size,
3510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              FixedArray::kHeaderSize));
35113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(string, &bailout);
3512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
35148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ and_(scratch, Immediate(
35158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
35168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
35178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
3518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ add(string_length,
3519b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kLengthOffset));
3520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(overflow, &bailout);
35213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(index, Immediate(1));
35223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(index, array_length);
3523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(less, &loop);
3524b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3525b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // If array_length is 1, return elements[0], a string.
3526b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(array_length, 1);
3527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(not_equal, &not_size_one_array);
3528b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
3529b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(result_operand, scratch);
3530b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&done);
3531b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3532b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&not_size_one_array);
3533b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // End of array_length live range.
3535b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  result_pos = array_length;
3536b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  array_length = no_reg;
3537b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live registers:
3539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // string_length: Sum of string lengths, as a smi.
3540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // elements: FixedArray of strings.
3541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3542b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check that the separator is a flat ASCII string.
3543b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, separator_operand);
35443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(string, &bailout);
3545b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3546b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
35478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ and_(scratch, Immediate(
35488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmp(scratch, ASCII_STRING_TYPE);
35508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ j(not_equal, &bailout);
35518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3552b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Add (separator length times array_length) - separator length
3553b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // to string_length.
3554b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, separator_operand);
3555b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset));
35563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(string_length, scratch);  // May be negative, temporarily.
3557b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ imul(scratch, array_length_operand);
3558b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(overflow, &bailout);
35593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(string_length, scratch);
3560b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(overflow, &bailout);
3561b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3562b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
35638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Live registers and stack values:
3564b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   string_length
3565b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   elements
3566b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ AllocateAsciiString(result_pos, string_length, scratch,
3567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                         index, string, &bailout);
3568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(result_operand, result_pos);
3569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
3570b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3571b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, separator_operand);
3573b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(FieldOperand(string, SeqAsciiString::kLengthOffset),
3574b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         Immediate(Smi::FromInt(1)));
3575b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(equal, &one_char_separator);
3576b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(greater, &long_separator);
3577b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3578b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3579b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Empty separator case
3580b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(index, Immediate(0));
3581b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&loop_1_condition);
35828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Loop condition: while (index < length).
3583b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_1);
3584b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Each iteration of the loop concatenates one string to the result.
3585b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live values in registers:
3586b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   index: which element of the elements array we are adding to the result.
3587b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   result_pos: the position to which we are currently copying characters.
3588b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   elements: the FixedArray of strings we are joining.
3589b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3590b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Get string = array[index].
3591b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, FieldOperand(elements, index,
3592b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              times_pointer_size,
3593b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              FixedArray::kHeaderSize));
3594b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string_length,
3595b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, String::kLengthOffset));
3596b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
3597b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(string,
3598b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kHeaderSize));
3599b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
36003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(index, Immediate(1));
3601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_1_condition);
3602b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(index, array_length_operand);
3603b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(less, &loop_1);  // End while (index < length).
3604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&done);
36058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
36068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3607b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3608b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // One-character separator case
3609b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&one_char_separator);
36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Replace separator with its ASCII character value.
3611b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov_b(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize));
3612b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov_b(separator_operand, scratch);
3613b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ Set(index, Immediate(0));
3615b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Jump into the loop after the code that copies the separator, so the first
3616b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // element is not preceded by a separator
3617b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&loop_2_entry);
3618b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Loop condition: while (index < length).
3619b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_2);
3620b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Each iteration of the loop concatenates one string to the result.
3621b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live values in registers:
3622b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   index: which element of the elements array we are adding to the result.
3623b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   result_pos: the position to which we are currently copying characters.
3624b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3625b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Copy the separator character to the result.
3626b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov_b(scratch, separator_operand);
3627b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov_b(Operand(result_pos, 0), scratch);
3628b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ inc(result_pos);
3629b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3630b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_2_entry);
3631b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Get string = array[index].
3632b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, FieldOperand(elements, index,
3633b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              times_pointer_size,
3634b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              FixedArray::kHeaderSize));
3635b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string_length,
3636b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, String::kLengthOffset));
3637b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
3638b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(string,
3639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kHeaderSize));
3640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
36413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(index, Immediate(1));
3642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3643b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(index, array_length_operand);
3644b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(less, &loop_2);  // End while (index < length).
3645b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&done);
3646b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3647b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Long separator case (separator is more than one character).
3649b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&long_separator);
3650b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3651b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ Set(index, Immediate(0));
3652b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Jump into the loop after the code that copies the separator, so the first
3653b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // element is not preceded by a separator
3654b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&loop_3_entry);
3655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Loop condition: while (index < length).
3656b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_3);
3657b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Each iteration of the loop concatenates one string to the result.
3658b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Live values in registers:
3659b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   index: which element of the elements array we are adding to the result.
3660b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  //   result_pos: the position to which we are currently copying characters.
3661b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3662b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Copy the separator to the result.
3663b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, separator_operand);
3664b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string_length,
3665b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, String::kLengthOffset));
3666b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
3667b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(string,
3668b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kHeaderSize));
3669b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
3670b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3671b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&loop_3_entry);
3672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Get string = array[index].
3673b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string, FieldOperand(elements, index,
3674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              times_pointer_size,
3675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              FixedArray::kHeaderSize));
3676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(string_length,
3677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, String::kLengthOffset));
3678b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ shr(string_length, 1);
3679b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ lea(string,
3680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         FieldOperand(string, SeqAsciiString::kHeaderSize));
3681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ CopyBytes(string, result_pos, string_length, scratch);
36823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(index, Immediate(1));
3683b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3684b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(index, array_length_operand);
3685b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ j(less, &loop_3);  // End while (index < length).
3686b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ jmp(&done);
3687b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
36888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
36898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&bailout);
369044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(result_operand, isolate()->factory()->undefined_value());
36918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&done);
3692b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ mov(eax, result_operand);
36938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Drop temp values from the stack, and restore context register.
36943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(esp, Immediate(3 * kPointerSize));
36958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
36968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
36978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  context()->Plug(eax);
36988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
36998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
37008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3701d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<String> name = expr->name();
3703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (name->length() > 0 && name->Get(0) == '_') {
3704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Comment cmnt(masm_, "[ InlineRuntimeCall");
3705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    EmitInlineRuntimeCall(expr);
3706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Comment cmnt(masm_, "[ CallRuntime");
37103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ZoneList<Expression*>* args = expr->arguments();
37113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Prepare for calling JS runtime function.
37148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(eax, GlobalObjectOperand());
3715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
3716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
37173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
37183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Push the arguments ("left-to-right").
37193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int arg_count = args->length();
37203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < arg_count; i++) {
37210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    VisitForStackValue(args->at(i));
3722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (expr->is_jsruntime()) {
3725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Call the JS runtime function via a call IC.
3726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ Set(ecx, Immediate(expr->name()));
3727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
3728589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Handle<Code> ic =
3729589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallIC(ic, mode, expr->id());
37310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Restore context register.
3732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
3734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Call the C runtime function.
3735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ CallRuntime(expr->function(), arg_count);
3736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
37370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
3738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (expr->op()) {
3743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    case Token::DELETE: {
3744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3745589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Property* property = expr->expression()->AsProperty();
3746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      VariableProxy* proxy = expr->expression()->AsVariableProxy();
3747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3748589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (property != NULL) {
3749589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->obj());
3750589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        VisitForStackValue(property->key());
37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ? kNonStrictMode : kStrictMode;
37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(Immediate(Smi::FromInt(strict_mode_flag)));
375469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
375569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        context()->Plug(eax);
3756589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (proxy != NULL) {
3757589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        Variable* var = proxy->var();
3758e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Delete of an unqualified identifier is disallowed in strict mode
3759589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        // but "delete this" is allowed.
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
3761589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (var->IsUnallocated()) {
3762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(GlobalObjectOperand());
3763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(var->name()));
3764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(Smi::FromInt(kNonStrictMode)));
3765e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(eax);
3767589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
3768589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // Result of deleting non-global variables is false.  'this' is
3769589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // not really a variable, though we implement it as one.  The
3770589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // subexpression does not have side effects.
3771589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          context()->Plug(var->is_this());
3772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
3773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Non-global variable.  Call the runtime to try to delete from the
3774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // context where the variable was introduced.
3775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(context_register());
3776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ push(Immediate(var->name()));
3777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
3778e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          context()->Plug(eax);
3779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
37801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
3781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Result of deleting non-property, non-variable reference is true.
3782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // The subexpression may have side effects.
3783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
3784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        context()->Plug(true);
3785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
3786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      break;
3787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
3788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::VOID: {
3790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      VisitForEffect(expr->expression());
379244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      context()->Plug(isolate()->factory()->undefined_value());
3793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
37943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
3795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::NOT: {
3797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (context()->IsEffect()) {
3799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Unary NOT has no side effects so it's only necessary to visit the
3800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // subexpression.  Match the optimizing compiler by not branching.
3801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        VisitForEffect(expr->expression());
38023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (context()->IsTest()) {
38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const TestContext* test = TestContext::cast(context());
38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The labels are swapped for the recursive call.
38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->false_label(),
38073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->true_label(),
38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        test->fall_through());
38093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        context()->Plug(test->true_label(), test->false_label());
3810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // We handle value contexts explicitly rather than simply visiting
38123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for control and plugging the control flow into the context,
38133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // because we need to prepare a pair of extra administrative AST ids
38143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // for the optimizing compiler.
38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label materialize_true, materialize_false, done;
38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VisitForControl(expr->expression(),
38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_false,
38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true,
38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &materialize_true);
38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_true);
38223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
38233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsAccumulatorValue()) {
38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ mov(eax, isolate()->factory()->true_value());
38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
38263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Push(isolate()->factory()->true_value());
38273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&done, Label::kNear);
38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&materialize_false);
38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (context()->IsAccumulatorValue()) {
38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ mov(eax, isolate()->factory()->false_value());
38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Push(isolate()->factory()->false_value());
38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&done);
3837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
3838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::TYPEOF: {
3842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
38430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      { StackValueContext context(this);
38440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        VisitForTypeofValue(expr->expression());
38450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallRuntime(Runtime::kTypeof, 1);
38470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(eax);
3848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
3849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
3850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3851d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Token::ADD: {
3852d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Comment cmt(masm_, "[ UnaryOperation (ADD)");
38530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->expression());
3854d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Label no_conversion;
38553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ JumpIfSmi(result_register(), &no_conversion);
38561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ToNumberStub convert_stub;
38571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ CallStub(&convert_stub);
3858d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      __ bind(&no_conversion);
38590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      context()->Plug(result_register());
3860d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
3861d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3862d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::SUB:
3864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
38654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
38664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case Token::BIT_NOT:
3868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
38694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      break;
38704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default:
3872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
38733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
3874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
3878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           const char* comment) {
3879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Comment cmt(masm_, comment);
3880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOverwriteMode overwrite =
3882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
3883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOpStub stub(expr->op(), overwrite);
3884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // UnaryOpStub expects the argument to be in the
3885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // accumulator register eax.
3886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VisitForAccumulatorValue(expr->expression());
3887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SetSourcePosition(expr->position());
38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
3889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  context()->Plug(eax);
3890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CountOperation");
389580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
389680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
3898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // as the left-hand side.
3899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!expr->expression()->IsValidLeftHandSide()) {
39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForEffect(expr->expression());
3901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return;
3902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
3903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Expression can only be a property, a global or a (parameter or local)
39053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // slot.
3906e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3907e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LhsKind assign_type = VARIABLE;
3908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Property* prop = expr->expression()->AsProperty();
3909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // In case of a property we use the uninitialized expression context
3910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // of the key to detect a named property.
3911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (prop != NULL) {
3912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    assign_type =
3913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Evaluate expression and get value.
3917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (assign_type == VARIABLE) {
3918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
39190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    AccumulatorValueContext context(this);
39203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitVariableLoad(expr->expression()->AsVariableProxy());
3921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
3922e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Reserve space for result of postfix operation.
39230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (expr->is_postfix() && !context()->IsEffect()) {
3924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ push(Immediate(Smi::FromInt(0)));
3925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (assign_type == NAMED_PROPERTY) {
3927402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // Put the object both on the stack and in the accumulator.
39280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(prop->obj());
3929402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(eax);
3930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitNamedPropertyLoad(prop);
3931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
39323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForStackValue(prop->obj());
39333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForAccumulatorValue(prop->key());
3934402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ mov(edx, Operand(esp, 0));
3935402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(eax);
3936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      EmitKeyedPropertyLoad(prop);
3937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We need a second deoptimization point after loading the value
3941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // in case evaluating the property load my have a side effect.
39428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (assign_type == VARIABLE) {
39438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrepareForBailout(expr->expression(), TOS_REG);
39448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } else {
39458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    PrepareForBailoutForId(expr->CountId(), TOS_REG);
39468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3948d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call ToNumber only if operand is not a smi.
3949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label no_conversion;
395080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
39513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(eax, &no_conversion, Label::kNear);
395280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
39531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ToNumberStub convert_stub;
39541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CallStub(&convert_stub);
3955d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&no_conversion);
39563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Save result for postfix expressions.
3958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (expr->is_postfix()) {
39590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!context()->IsEffect()) {
39600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Save the result on the stack. If we have a named or keyed property
39610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // we store the result under the receiver that is currently on top
39620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // of the stack.
39630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      switch (assign_type) {
39640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case VARIABLE:
39650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ push(eax);
39660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
39670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case NAMED_PROPERTY:
39680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ mov(Operand(esp, kPointerSize), eax);
39690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
39700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case KEYED_PROPERTY:
39710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          __ mov(Operand(esp, 2 * kPointerSize), eax);
39720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
39730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
3974e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
3975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
3976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
3977d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Inline smi case if we are in a loop.
3978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done, stub_call;
3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  JumpPatchSite patch_site(masm_);
3980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
398180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (ShouldInlineSmiCase(expr->op())) {
3982d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
39833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(eax, Immediate(Smi::FromInt(1)));
3984d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sub(eax, Immediate(Smi::FromInt(1)));
3986d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(overflow, &stub_call, Label::kNear);
3988d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // We could eliminate this smi check if we split the code at
3989d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the first smi check before calling ToNumber.
3990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    patch_site.EmitJumpIfSmi(eax, &done, Label::kNear);
3991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3992d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&stub_call);
3993d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call stub. Undo operation first.
3994d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (expr->op() == Token::INC) {
39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sub(eax, Immediate(Smi::FromInt(1)));
3996d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(eax, Immediate(Smi::FromInt(1)));
3998d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
3999d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
4000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Record position before stub call.
4002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SetSourcePosition(expr->position());
4003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call stub for +1/-1.
4005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(edx, eax);
4006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(eax, Immediate(Smi::FromInt(1)));
4007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
40093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  patch_site.EmitPatchInfo();
4010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
4011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store the value returned in eax.
4013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  switch (assign_type) {
4014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case VARIABLE:
4015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
4016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
40170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        { EffectContext context(this);
40180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
40190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                 Token::ASSIGN);
4020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          context.Plug(eax);
40220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        }
40230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // For all contexts except EffectContext We have the result on
4024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // top of the stack.
40250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
40260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4027e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
4029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Perform the assignment as if via '='.
4030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
40310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               Token::ASSIGN);
4032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        context()->Plug(eax);
4034e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4036e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case NAMED_PROPERTY: {
4037e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ecx, prop->key()->AsLiteral()->handle());
40384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      __ pop(edx);
40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->StoreIC_Initialize()
40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->StoreIC_Initialize_Strict();
40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
4043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
40450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
40460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4048e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
40490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(eax);
4050e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case KEYED_PROPERTY: {
40546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(ecx);
40556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(edx);
40563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> ic = is_classic_mode()
40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? isolate()->builtins()->KeyedStoreIC_Initialize()
40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
40593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
4060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (expr->is_postfix()) {
40626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Result is on the stack
40630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (!context()->IsEffect()) {
40640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          context()->PlugTOS();
4065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        }
4066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
40670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        context()->Plug(eax);
4068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
4069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
40713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
40723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
40733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
40743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
40750d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
407680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VariableProxy* proxy = expr->AsVariableProxy();
40770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsEffect());
40780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!context()->IsTest());
40790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4080589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (proxy != NULL && proxy->var()->IsUnallocated()) {
408180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Comment cmnt(masm_, "Global variable");
40828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ mov(eax, GlobalObjectOperand());
408380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(ecx, Immediate(proxy->name()));
408444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
408580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Use a regular load, not a contextual load, to avoid a reference
408680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // error.
40873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallIC(ic);
4088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr, TOS_REG);
40890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
4090589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
409159151504615d929945dc59db37bf1166937748c6Steve Block    Label done, slow;
409259151504615d929945dc59db37bf1166937748c6Steve Block
409359151504615d929945dc59db37bf1166937748c6Steve Block    // Generate code for loading from variables potentially shadowed
409459151504615d929945dc59db37bf1166937748c6Steve Block    // by eval-introduced variables.
4095589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
409659151504615d929945dc59db37bf1166937748c6Steve Block
409759151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&slow);
409880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(esi);
409980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ push(Immediate(proxy->name()));
410080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
4101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailout(expr, TOS_REG);
410259151504615d929945dc59db37bf1166937748c6Steve Block    __ bind(&done);
410359151504615d929945dc59db37bf1166937748c6Steve Block
41040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    context()->Plug(eax);
410580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
410680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // This expression cannot throw a reference error at the top level.
41073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitInDuplicateContext(expr);
4108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
4109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
41103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
41113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
41123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
41133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Expression* sub_expr,
41143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 Handle<String> check) {
41153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label materialize_true, materialize_false;
41163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_true = NULL;
41173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* if_false = NULL;
41183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label* fall_through = NULL;
41193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->PrepareTest(&materialize_true, &materialize_false,
41203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         &if_true, &if_false, &fall_through);
41213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  { AccumulatorValueContext context(this);
41233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForTypeofValue(sub_expr);
41240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
41253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
41260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
412744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (check->Equals(isolate()->heap()->number_symbol())) {
4128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_true);
412980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
413044f0eee88ff00398ff7f715fab053374d808c90dSteve Block           isolate()->factory()->heap_number_map());
413180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
413244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->string_symbol())) {
4133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_false);
4134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
4135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(above_equal, if_false);
413680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
4137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
4138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              1 << Map::kIsUndetectable);
4139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
414044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
414144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(eax, isolate()->factory()->true_value());
4142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
414344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(eax, isolate()->factory()->false_value());
414480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
414569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  } else if (FLAG_harmony_typeof &&
414669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch             check->Equals(isolate()->heap()->null_symbol())) {
414769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ cmp(eax, isolate()->factory()->null_value());
414869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Split(equal, if_true, if_false, fall_through);
414944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
415044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(eax, isolate()->factory()->undefined_value());
4151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    __ j(equal, if_true);
4152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_false);
415380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => true.
415480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
415580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
415680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(ecx, Immediate(1 << Map::kIsUndetectable));
415780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
415844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->function_symbol())) {
4159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_false);
41603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
41613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
41623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, if_true);
41633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
41643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Split(equal, if_true, if_false, fall_through);
416544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (check->Equals(isolate()->heap()->object_symbol())) {
4166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ JumpIfSmi(eax, if_false);
416769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!FLAG_harmony_typeof) {
416869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ cmp(eax, isolate()->factory()->null_value());
416969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ j(equal, if_true);
417069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
41713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CmpObjectType(eax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, edx);
4172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ j(below, if_false);
41733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CmpInstanceType(edx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
41743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ j(above, if_false);
417580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check for undetectable objects => false.
4176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
4177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              1 << Map::kIsUndetectable);
4178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Split(zero, if_true, if_false, fall_through);
417980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
418080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (if_false != fall_through) __ jmp(if_false);
4181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
41823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context()->Plug(if_true, if_false);
4183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
4184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4186d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Comment cmnt(masm_, "[ CompareOperation");
418880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SetSourcePosition(expr->position());
4189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // First we try a fast inlined version of the compare when one of
41913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the operands is a literal.
41923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (TryLiteralCompare(expr)) return;
41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Always perform the comparison for its control flow.  Pack the result
4195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // into the expression's context after the comparison is performed.
4196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label materialize_true, materialize_false;
4197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_true = NULL;
4198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Label* if_false = NULL;
419980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
42000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
42010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
420280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
42033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Token::Value op = expr->op();
42040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->left());
42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (op) {
4206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    case Token::IN:
42070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
421044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmp(eax, isolate()->factory()->true_value());
421180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(equal, if_true, if_false, fall_through);
4212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
42133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case Token::INSTANCEOF: {
42150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForStackValue(expr->right());
4216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      InstanceofStub stub(InstanceofStub::kNoFlags);
4217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      __ CallStub(&stub);
42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ test(eax, eax);
422080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // The stub returns 0 for true.
422180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(zero, if_true, if_false, fall_through);
4222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
4223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
4224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: {
42260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      VisitForAccumulatorValue(expr->right());
4227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Condition cc = no_condition;
422880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      switch (op) {
4229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::EQ_STRICT:
423080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        case Token::EQ:
4231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = equal;
4232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LT:
4234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = less;
4235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GT:
42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          cc = greater;
4238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block         break;
4239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::LTE:
42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          cc = less_equal;
4241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::GTE:
4243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          cc = greater_equal;
4244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
4245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::IN:
4246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case Token::INSTANCEOF:
4247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
4248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          UNREACHABLE();
4249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(edx);
4251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
42520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      bool inline_smi_code = ShouldInlineSmiCase(op);
4253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JumpPatchSite patch_site(masm_);
42540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (inline_smi_code) {
4255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label slow_case;
42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(ecx, edx);
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ or_(ecx, eax);
4258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ cmp(edx, eax);
426080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Split(cc, if_true, if_false, NULL);
426180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&slow_case);
426280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
4263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Record position and call the compare IC.
4265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SetSourcePosition(expr->position());
4266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Handle<Code> ic = CompareIC::GetUninitialized(op);
42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
42683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      patch_site.EmitPatchInfo();
4269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ test(eax, eax);
427280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Split(cc, if_true, if_false, fall_through);
4273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
42743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
42753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convert the result of the comparison into one expected for this
4277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // expression's context.
42780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
4279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Expression* sub_expr,
42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              NilValue nil) {
428580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label materialize_true, materialize_false;
428680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_true = NULL;
428780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* if_false = NULL;
428880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label* fall_through = NULL;
42890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->PrepareTest(&materialize_true, &materialize_false,
42900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         &if_true, &if_false, &fall_through);
429180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitForAccumulatorValue(sub_expr);
42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> nil_value = nil == kNullValue ?
42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->null_value() :
42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->undefined_value();
42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, nil_value);
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->op() == Token::EQ_STRICT) {
429980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(equal, if_true, if_false, fall_through);
430080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> other_nil_value = nil == kNullValue ?
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->undefined_value() :
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate()->factory()->null_value();
430480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(eax, other_nil_value);
430680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ j(equal, if_true);
43073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(eax, if_false);
430880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // It can be an undetectable object.
430980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
431080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset));
431180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ test(edx, Immediate(1 << Map::kIsUndetectable));
431280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Split(not_zero, if_true, if_false, fall_through);
431380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
43140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(if_true, if_false);
431580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
431680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
431780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
43200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(eax);
43210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
43220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
43230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
43240d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() {
43250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return eax;
4326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
43290d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() {
43300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return esi;
43310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4334d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(Operand(ebp, frame_offset), value);
43373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
43383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
43393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4340d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
434159151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(dst, ContextOperand(esi, context_index));
4342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
43453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
43463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* declaration_scope = scope()->DeclarationScope();
43473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (declaration_scope->is_global_scope()) {
43483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts nested in the global context have a canonical empty function
43493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // as their closure, not the anonymous closure containing the global
43503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // code.  Pass a smi sentinel and let the runtime look up the empty
43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // function.
43523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ push(Immediate(Smi::FromInt(0)));
43533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (declaration_scope->is_eval_scope()) {
43543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Contexts nested inside eval code have the same closure as the context
43553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // calling eval, not the anonymous closure containing the eval code.
43563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Fetch it from the context.
43573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ push(ContextOperand(esi, Context::CLOSURE_INDEX));
43583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
43593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(declaration_scope->is_function_scope());
43603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
43613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
43623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
43633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ----------------------------------------------------------------------------
4366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support.
4367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4368d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() {
4369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Cook return address on top of stack (smi encoded Code* delta)
4370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(edx));
43713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(edx);
43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(edx, Immediate(masm_->CodeObject()));
437369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
437469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
43753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiTag(edx);
43763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(edx);
4377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Store result register while executing finally block.
4378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(result_register());
4379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() {
4383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!result_register().is(edx));
4384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ pop(result_register());
4385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Uncook return address.
43863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(edx);
43873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiUntag(edx);
43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(edx, Immediate(masm_->CodeObject()));
43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(edx);
4390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __
4394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
439569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm())
439669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
439769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
439869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* stack_depth,
439969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* context_length) {
440069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The macros used here must preserve the result register.
440169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
440269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Because the handler block contains the context of the finally
440369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // code, we can restore it directly from there for the finally code
440469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // rather than iteratively unwinding contexts via their previous
440569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // links.
440669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Drop(*stack_depth);  // Down to the handler block.
440769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (*context_length > 0) {
440869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Restore the context to its dedicated register and the stack.
440969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ mov(esi, Operand(esp, StackHandlerConstants::kContextOffset));
441069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
441169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
441269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ PopTryHandler();
441369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ call(finally_entry_);
441469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
441569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *stack_depth = 0;
441669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *context_length = 0;
441769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return previous_;
441869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
441969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
442069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
442169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __
442269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
44233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} }  // namespace v8::internal
4424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
4426