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