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, ¬_found); 3342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1)); 3344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 3345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_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, ¬_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(¬_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