13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 23ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Redistribution and use in source and binary forms, with or without 33ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// modification, are permitted provided that the following conditions are 43ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// met: 53ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 63ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Redistributions of source code must retain the above copyright 73ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// notice, this list of conditions and the following disclaimer. 83ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Redistributions in binary form must reproduce the above 93ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// copyright notice, this list of conditions and the following 103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// disclaimer in the documentation and/or other materials provided 113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// with the distribution. 123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Neither the name of Google Inc. nor the names of its 133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// contributors may be used to endorse or promote products derived 143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// from this software without specific prior written permission. 153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "v8.h" 293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h" 338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h" 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h" 353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#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 443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED { 481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 49589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block info_emitted_ = false; 521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ~JumpPatchSite() { 561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(patch_site_.is_bound() == info_emitted_); 571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJumpIfNotSmi(Register reg, 60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* target, 61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar) { 621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(reg, Immediate(kSmiTagMask)); 63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitJump(not_carry, target, near_jump); // Always taken before patched. 641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJumpIfSmi(Register reg, 67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* target, 68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar) { 691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(reg, Immediate(kSmiTagMask)); 70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitJump(carry, target, near_jump); // Never taken before patched. 711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitPatchInfo() { 743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (patch_site_.is_bound()) { 753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); 763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(is_int8(delta_to_patch_site)); 773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ testl(rax, Immediate(delta_to_patch_site)); 781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info_emitted_ = true; 801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(); // Signals no inlined code. 833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // jc will be patched with jz, jnc will become jnz. 88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJump(Condition cc, Label* target, Label::Distance near_jump) { 891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!patch_site_.is_bound() && !info_emitted_); 901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(cc == carry || cc == not_carry); 911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(cc, target, near_jump); 931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block MacroAssembler* masm_; 961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label patch_site_; 971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool info_emitted_; 991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 1001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}; 1011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint FullCodeGenerator::self_optimization_header_size() { 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return 20; 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 1093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the 1103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them. The actual argument count matches the 1113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function. 1123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 1133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// o rdi: the JS function object being called (i.e. ourselves) 1153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsi: our context 1163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rbp: our caller's frame pointer 1173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsp: stack pointer (pointing to return address) 1183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout. 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() { 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompilationInfo* info = info_; 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch handler_table_ = 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 1266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 1273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We can optionally optimize based on counters rather than statistical 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sampling. 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (info->ShouldSelfOptimize()) { 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_opt_verbose) { 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("[adding self-optimization header to %s]\n", 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *info->function()->debug_name()->ToCString()); 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch has_self_optimization_header_ = true; 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell( 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt)); 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSGlobalPropertyCell* cell; 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (maybe_cell->To(&cell)) { 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rax, Handle<JSGlobalPropertyCell>(cell), 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::EMBEDDED_OBJECT); 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiAddConstant(FieldOperand(rax, JSGlobalPropertyCell::kValueOffset), 1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(-1)); 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> compile_stub( 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->builtins()->builtin(Builtins::kLazyRecompile)); 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, compile_stub, RelocInfo::CODE_TARGET); 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(masm_->pc_offset() == self_optimization_header_size()); 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 151f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG 152f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (strlen(FLAG_stop_at) > 0 && 153f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 154f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ int3(); 155f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 156f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif 157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Strict mode functions and builtins need to replace the receiver 1593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // with undefined when called as functions (without an explicit 1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // receiver object). rcx is zero for method calls and non-zero for 1613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // function calls. 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!info->is_classic_mode() || info->is_native()) { 163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testq(rcx, rcx); 165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &ok, Label::kNear); 166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // +1 for return address. 1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; 168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(Operand(rsp, receiver_offset), kScratchRegister); 170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ok); 171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the frame (that is done below). 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 178756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rbp); // Caller's frame pointer. 179756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(rbp, rsp); 180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rsi); // Callee's context. 181756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdi); // Callee's JS Function. 182756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 183756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int locals_count = info->scope()->num_stack_slots(); 185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (locals_count == 1) { 186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ PushRoot(Heap::kUndefinedValueRootIndex); 187756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (locals_count > 1) { 188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < locals_count; i++) { 190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdx); 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 193756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bool function_in_register = true; 1964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots > 0) { 200756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate local context"); 201756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Argument to NewContext is the function, which is still in rdi. 202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdi); 203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots <= FastNewContextStub::kMaximumSlots) { 204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastNewContextStub stub(heap_slots); 205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick function_in_register = false; 210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Context is returned in both rax and rsi. It replaces the context 211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // passed to us. It's saved in the stack and kept live in rsi. 212756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 213756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 214756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy any necessary parameters into the context. 2153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < num_parameters; i++) { 217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = scope()->parameter(i); 218589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 219756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int parameter_offset = StandardFrameConstants::kCallerSPOffset + 220756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick (num_parameters - 1 - i) * kPointerSize; 221756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load parameter from stack. 222756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(rax, Operand(rbp, parameter_offset)); 223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_offset = Context::SlotOffset(var->index()); 225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(Operand(rsi, context_offset), rax); 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier. This clobbers rax and rbx. 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot( 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rsi, context_offset, rax, rbx, kDontSaveFPRegs); 229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 2323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate an arguments object. 2340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Variable* arguments = scope()->arguments(); 235756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (arguments != NULL) { 236756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments object must be allocated after the context object, in 237756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // case the "arguments" or ".arguments" variables are in the context. 238756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate arguments object"); 239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (function_in_register) { 240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdi); 241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The receiver is just before the parameters on the caller's stack. 2453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int offset = num_parameters * kPointerSize; 247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ lea(rdx, 248756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 249756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdx); 2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Push(Smi::FromInt(num_parameters)); 251756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments to ArgumentsAccessStub: 252756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // function, receiver address, parameter count. 253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The stub will rewrite receiver and parameter count if the previous 254756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // stack frame was an arguments adapter frame. 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ArgumentsAccessStub::Type type; 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!is_classic_mode()) { 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type = ArgumentsAccessStub::NEW_STRICT; 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (function()->has_duplicate_parameters()) { 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ArgumentsAccessStub stub(type); 264756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 26544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SetVar(arguments, rax, rbx, rdx); 267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace) { 270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Visit the declarations and body unless there is an illegal 274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // redeclaration. 275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope()->HasIllegalRedeclaration()) { 276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment cmnt(masm_, "[ Declarations"); 277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scope()->VisitIllegalRedeclaration(this); 278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); 281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Declarations"); 282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // For named function expressions, declare the function name as a 283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // constant. 284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope()->is_function_scope() && scope()->function() != NULL) { 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VariableProxy* proxy = scope()->function(); 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(proxy->var()->mode() == CONST || 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch proxy->var()->mode() == CONST_HARMONY); 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(proxy->var()->location() != Variable::UNALLOCATED); 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitDeclaration(proxy, proxy->var()->mode(), NULL); 290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitDeclarations(scope()->declarations()); 292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Stack check"); 295589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); 296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &ok, Label::kNear); 299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StackCheckStub stub; 300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&ok); 302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Body"); 305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(loop_depth() == 0); 306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitStatements(function()->body()); 307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(loop_depth() == 0); 308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Always emit a 'return undefined' in case control fell off the end of 312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the body. 3133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 3143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 3157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 320db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() { 3219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Set(rax, 0); 322db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch} 323db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 324db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* back_edge_target) { 327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Comment cmnt(masm_, "[ Stack check"); 328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &ok, Label::kNear); 331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StackCheckStub stub; 332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallStub(&stub); 333086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of this PC offset to the OSR id. This is used to find 334086aeeaae12517475c22695a200be45495516549Ben Murdoch // the AST id from the unoptimized code in order to use it as a key into 335086aeeaae12517475c22695a200be45495516549Ben Murdoch // the deoptimization input data found in the optimized code. 336086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordStackCheck(stmt->OsrEntryId()); 337086aeeaae12517475c22695a200be45495516549Ben Murdoch 338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Loop stack checks can be patched to perform on-stack replacement. In 339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // order to decide whether or not to perform OSR we embed the loop depth 340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // in a test instruction after the call so we can extract it from the OSR 341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // builtin. 342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(loop_depth() > 0); 343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(rax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker))); 344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&ok); 346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 347086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of the OSR id to this PC. This is used if the OSR 348086aeeaae12517475c22695a200be45495516549Ben Murdoch // entry becomes the target of a bailout. We don't expect it to be, but 349086aeeaae12517475c22695a200be45495516549Ben Murdoch // we want it to work if it is. 350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); 351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 3603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 3613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 3623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 3633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 369bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 3703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ RecordJSReturn(); 3713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Do not use the leave instruction here because it is too short to 3723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // patch with the code required by the debugger. 3733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsp, rbp); 3743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(rbp); 3751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize; 3771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(arguments_bytes, rcx); 3781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 3803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Add padding that will be overwritten by a debugger breakpoint. We 3811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k" 3823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // (3 + 1 + 3). 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const int kPadding = Assembler::kJSReturnSequenceLength - 7; 3843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < kPadding; ++i) { 3853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block masm_->int3(); 3863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the size of the code used for returning is large enough 3881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // for the debugger's requirements. 3891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(Assembler::kJSReturnSequenceLength <= 3901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 3913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif 3923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 3943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 396589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const { 397589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand operand = codegen()->VarOperand(var, result_register()); 410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(operand); 411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const { 415589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 4173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ PushRoot(index); 4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (index == Heap::kUndefinedValueRootIndex || 4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kNullValueRootIndex || 4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kFalseValueRootIndex) { 445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (index == Heap::kTrueValueRootIndex) { 447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 4503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 4560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4590d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 4600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 4610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), lit); 4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 4660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Push(lit); 4670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsTrue() || lit->IsJSObject()) { 479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 4800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 4810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 4830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 4850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 4860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 4910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), lit); 4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count, 5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int count, 5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count > 1) __ Drop(count - 1); 5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(Operand(rsp, 0), reg); 521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count, 5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 5260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 5270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 5313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 5320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(materialize_true == materialize_false); 5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(result_register(), isolate()->factory()->true_value()); 548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 55044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(result_register(), isolate()->factory()->false_value()); 5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 5590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 56044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(isolate()->factory()->true_value()); 561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 5620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 56344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(isolate()->factory()->false_value()); 5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(materialize_true == true_label_); 571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(materialize_false == false_label_); 5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const { 5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), value_root_index); 5830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ PushRoot(value_root_index); 5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 595086aeeaae12517475c22695a200be45495516549Ben Murdoch true, 596086aeeaae12517475c22695a200be45495516549Ben Murdoch true_label_, 597086aeeaae12517475c22695a200be45495516549Ben Murdoch false_label_); 5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ jmp(true_label_); 6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ jmp(false_label_); 602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 6063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition, 6073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* if_true, 60880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 60980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ToBooleanStub stub(result_register()); 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 6133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ testq(result_register(), result_register()); 61480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns nonzero for true. 61580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 61680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 61980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc, 62080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 62180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 62280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 62380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 62480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 62580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 62680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(NegateCondition(cc), if_false); 62780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 62880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 62980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(if_false); 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 634589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) { 635589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated()); 636589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Offset is negative because higher indexes are at lower addresses. 637589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = -var->index() * kPointerSize; 638589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Adjust by a (parameter or local) base offset. 639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsParameter()) { 640589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += (info_->scope()->num_parameters() + 1) * kPointerSize; 641589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 642589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += JavaScriptFrameConstants::kLocal0Offset; 643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 644589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Operand(rbp, offset); 645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 648589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 649589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 650589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 651589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_chain_length = scope()->ContextChainLength(var->scope()); 652589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ LoadContext(scratch, context_chain_length); 653589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(scratch, var->index()); 654589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 655589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return StackOperand(var); 656589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 660589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) { 661589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 662589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, dest); 663589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(dest, location); 664589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 665589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 666589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 667589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var, 668589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register src, 669589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch0, 670589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1) { 671589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 672589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(!scratch0.is(src)); 673589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(!scratch0.is(scratch1)); 674589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(!scratch1.is(src)); 675589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, scratch0); 676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(location, src); 6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 679589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 680589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = Context::SlotOffset(var->index()); 6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); 682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool should_normalize, 688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_true, 689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_false) { 690086aeeaae12517475c22695a200be45495516549Ben Murdoch // Only prepare for bailouts before splits if we're in a test 691086aeeaae12517475c22695a200be45495516549Ben Murdoch // context. Otherwise, we let the Visit function deal with the 692086aeeaae12517475c22695a200be45495516549Ben Murdoch // preparation to avoid preparing with the same AST id twice. 693086aeeaae12517475c22695a200be45495516549Ben Murdoch if (!context()->IsTest() || !info_->IsOptimizable()) return; 694086aeeaae12517475c22695a200be45495516549Ben Murdoch 695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip; 696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (should_normalize) __ jmp(&skip, Label::kNear); 6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailout(expr, TOS_REG); 698086aeeaae12517475c22695a200be45495516549Ben Murdoch if (should_normalize) { 699086aeeaae12517475c22695a200be45495516549Ben Murdoch __ CompareRoot(rax, Heap::kTrueValueRootIndex); 700086aeeaae12517475c22695a200be45495516549Ben Murdoch Split(equal, if_true, if_false, NULL); 701086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(&skip); 702086aeeaae12517475c22695a200be45495516549Ben Murdoch } 703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 706589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VariableMode mode, 7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FunctionLiteral* function) { 709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If it was not possible to allocate the variable at compile time, we 710589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // need to "declare" it at runtime to make sure it actually exists in the 711589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // local context. 712589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* variable = proxy->var(); 7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool binding_needs_init = (function == NULL) && 7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (mode == CONST || mode == CONST_HARMONY || mode == LET); 715589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (variable->location()) { 716589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++global_count_; 718589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 72269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (function != NULL) { 723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 72469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch VisitForAccumulatorValue(function); 725589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(StackOperand(variable), result_register()); 7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (binding_needs_init) { 727589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 72869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 729589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(StackOperand(variable), kScratchRegister); 730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 73169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 733589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: 73469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // The variable in the decl always resides in the current function 73569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // context. 73669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 73769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (FLAG_debug_code) { 73869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Check that we're not inside a with or catch context. 73969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); 74069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); 74169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Check(not_equal, "Declaration in with context."); 74269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); 74369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Check(not_equal, "Declaration in catch context."); 7441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 74569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (function != NULL) { 746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 74769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch VisitForAccumulatorValue(function); 748589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(ContextOperand(rsi, variable->index()), result_register()); 749589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = Context::SlotOffset(variable->index()); 7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We know that we have written a function, which is not a smi. 7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(rsi, 7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result_register(), 7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rcx, 7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 758589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (binding_needs_init) { 760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 76169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 762589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(ContextOperand(rsi, variable->index()), kScratchRegister); 76369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // No write barrier since the hole value is in old space. 764589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 76569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 76669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 768589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: { 769589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 77069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(rsi); 77169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(variable->name()); 7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Declaration nodes are always introduced in one of four modes. 7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(mode == VAR || 7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode == CONST || 7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode == CONST_HARMONY || 7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode == LET); 7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PropertyAttributes attr = 7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (mode == CONST || mode == CONST_HARMONY) ? READ_ONLY : NONE; 77969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(Smi::FromInt(attr)); 78069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Push initial value, if any. 78169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Note: For variables we must not push an initial value (such as 78269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // 'undefined') because we may have a (legal) redeclaration and we 78369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // must not destroy the current value. 78469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (function != NULL) { 78569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch VisitForStackValue(function); 7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (binding_needs_init) { 78769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ PushRoot(Heap::kTheHoleValueRootIndex); 78869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(Smi::FromInt(0)); // Indicates no initial value. 79069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 79169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CallRuntime(Runtime::kDeclareContextSlot, 4); 79269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 798d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 7993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 8003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rsi); // The context is the first argument. 8013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(pairs); 802589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(Smi::FromInt(DeclareGlobalsFlags())); 803589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kDeclareGlobals, 3); 8043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 8053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 812086aeeaae12517475c22695a200be45495516549Ben Murdoch 813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 8140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 815086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 8248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clause->body_target()->Unuse(); 8251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 8370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 83980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 8400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(rdx, Operand(rsp, 0)); // Switch value. 8410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 8421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 8430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_case; 8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rcx, rdx); 8461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ or_(rcx, rax); 847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 8481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpq(rdx, rax); 85080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &next_test); 85180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 8528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(clause->body_target()); 85380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 85480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 8561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position before stub call for type feedback. 8571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetSourcePosition(clause->position()); 8581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId()); 8603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 8611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testq(rax, rax); 863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 8658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(clause->body_target()); 866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 87369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(nested_statement.break_label()); 874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 8758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(default_clause->body_target()); 876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 8828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(clause->body_target()); 88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); 884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 88769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(nested_statement.break_label()); 888086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the object to enumerate over. Both SpiderMonkey and JSC 901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ignore null and undefined in contrast to the specification; see 902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ECMA-262 section 12.6.4. 9030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register null_value = rdi; 907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(null_value, Heap::kNullValueRootIndex); 908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmpq(rax, null_value); 909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &convert); 9163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, &done_convert); 918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for proxies. 9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_runtime; 9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); 9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(below_equal, &call_runtime); 9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check cache validity in generated code. This is a fast case for 931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the JSObject::IsSimpleEnum cache validity checks. If we cannot 932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // guarantee cache validity, call the runtime system to check cache 933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // validity or get the property names in a fixed array. 9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckEnumCache(null_value, &call_runtime); 935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The enum cache is valid. Load the map of the object being 937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // iterated over and use the cache for the iteration. 938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label use_cache; 939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&use_cache, Label::kNear); 941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&call_runtime); 944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Duplicate the enumerable object on the stack. 945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fixed_array; 951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Heap::kMetaMapRootIndex); 953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &fixed_array, Label::kNear); 954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register rax. Get the enumeration cache from it. 956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&use_cache); 957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadInstanceDescriptors(rax, rcx); 958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); 959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the four remaining stack slots. 962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Map. 963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rdx); // Enumeration cache. 964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); 965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Enumeration cache length (as smi). 966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Initial index. 967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register rax. Iterate through that. 9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label non_proxy; 971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell( 9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object>( 9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker))); 9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordTypeFeedbackCell(stmt->PrepareId(), cell); 9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(rbx, cell); 9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), 9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)); 9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check 9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object 9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx); 9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above, &non_proxy); 9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy 9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&non_proxy); 9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rbx); // Smi 9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rax); // Array 991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Fixed array length (as smi). 993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Initial index. 994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. 999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. 100069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, loop_statement.break_label()); 1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register rbx. 1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, Operand(rsp, 2 * kPointerSize)); 1004f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); 1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rbx, 1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 1007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize)); 1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the expected map from the stack or a smi in the 1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register rdx. 1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 3 * kPointerSize)); 1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If not, we may have to filter the key. 1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label update_each; 1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, Operand(rsp, 4 * kPointerSize)); 1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); 1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &update_each, Label::kNear); 1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For proxies, no filtering is done. 10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rdx, Smi::FromInt(0)); 10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &update_each, Label::kNear); 10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the entry to a string or null if it isn't a property 1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // anymore. If the property has been removed while iterating, we 1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rcx); // Enumerable. 1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rbx); // Current entry. 1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(rax, Smi::FromInt(0)); 103369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, loop_statement.continue_label()); 1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, rax); 1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register rbx. 1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(result_register(), rbx); 1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { EffectContext context(this); 10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAssignment(stmt->each()); 1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for going to the next element by incrementing the 1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // index (smi) stored on top of the stack. 105069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.continue_label()); 1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); 1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitStackCheck(stmt, &loop); 1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(&loop); 1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 105769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.break_label()); 1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ addq(rsp, Immediate(5 * kPointerSize)); 1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 10688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang bool pretenure) { 1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 1070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // space for nested functions that don't need literals cloning. If 1071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // we're running with the --always-opt or the --prepare-always-opt 1072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // flag, we need to use the runtime function so that the new function 1073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // we are creating here gets a chance to have its code optimized and 1074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // doesn't just get a copy of the existing unoptimized code. 1075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!FLAG_always_opt && 1076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !FLAG_prepare_always_opt && 107744f0eee88ff00398ff7f715fab053374d808c90dSteve Block !pretenure && 1078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scope()->is_function_scope() && 107944f0eee88ff00398ff7f715fab053374d808c90dSteve Block info->num_literals() == 0) { 10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastNewClosureStub stub(info->language_mode()); 1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(info); 1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rsi); 1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(info); 108644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(pretenure 108744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate()->factory()->true_value() 108844f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate()->factory()->false_value()); 10898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CallRuntime(Runtime::kNewClosure, 3); 1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 10910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1095d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 10973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr); 1098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1099e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1101589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, 1102589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TypeofState typeof_state, 1103589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 110459151504615d929945dc59db37bf1166937748c6Steve Block Register context = rsi; 110559151504615d929945dc59db37bf1166937748c6Steve Block Register temp = rdx; 110659151504615d929945dc59db37bf1166937748c6Steve Block 110759151504615d929945dc59db37bf1166937748c6Steve Block Scope* s = scope(); 110859151504615d929945dc59db37bf1166937748c6Steve Block while (s != NULL) { 110959151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (s->calls_non_strict_eval()) { 111159151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 111259151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 111359151504615d929945dc59db37bf1166937748c6Steve Block Immediate(0)); 111459151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 111559151504615d929945dc59db37bf1166937748c6Steve Block } 111659151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 11173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 111859151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering rsi. 111959151504615d929945dc59db37bf1166937748c6Steve Block context = temp; 112059151504615d929945dc59db37bf1166937748c6Steve Block } 112159151504615d929945dc59db37bf1166937748c6Steve Block // If no outer scope calls eval, we do not need to check more 112259151504615d929945dc59db37bf1166937748c6Steve Block // context extensions. If we have reached an eval scope, we check 112359151504615d929945dc59db37bf1166937748c6Steve Block // all extensions from this point. 11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; 112559151504615d929945dc59db37bf1166937748c6Steve Block s = s->outer_scope(); 112659151504615d929945dc59db37bf1166937748c6Steve Block } 112759151504615d929945dc59db37bf1166937748c6Steve Block 112859151504615d929945dc59db37bf1166937748c6Steve Block if (s != NULL && s->is_eval_scope()) { 112959151504615d929945dc59db37bf1166937748c6Steve Block // Loop up the context chain. There is no frame effect so it is 113059151504615d929945dc59db37bf1166937748c6Steve Block // safe to use raw labels here. 1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label next, fast; 113259151504615d929945dc59db37bf1166937748c6Steve Block if (!context.is(temp)) { 113359151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, context); 113459151504615d929945dc59db37bf1166937748c6Steve Block } 113559151504615d929945dc59db37bf1166937748c6Steve Block // Load map for comparison into register, outside loop. 113659151504615d929945dc59db37bf1166937748c6Steve Block __ LoadRoot(kScratchRegister, Heap::kGlobalContextMapRootIndex); 113759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&next); 113859151504615d929945dc59db37bf1166937748c6Steve Block // Terminate at global context. 113959151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset)); 1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &fast, Label::kNear); 114159151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 114259151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); 114359151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 114459151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 11453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); 114659151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(&next); 114759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&fast); 114859151504615d929945dc59db37bf1166937748c6Steve Block } 114959151504615d929945dc59db37bf1166937748c6Steve Block 115059151504615d929945dc59db37bf1166937748c6Steve Block // All extension objects were empty and it is safe to use a global 115159151504615d929945dc59db37bf1166937748c6Steve Block // load IC call. 11528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(rax, GlobalObjectOperand()); 1153589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Move(rcx, var->name()); 115444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 115559151504615d929945dc59db37bf1166937748c6Steve Block RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 115659151504615d929945dc59db37bf1166937748c6Steve Block ? RelocInfo::CODE_TARGET 115759151504615d929945dc59db37bf1166937748c6Steve Block : RelocInfo::CODE_TARGET_CONTEXT; 11583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, mode); 115959151504615d929945dc59db37bf1166937748c6Steve Block} 116059151504615d929945dc59db37bf1166937748c6Steve Block 116159151504615d929945dc59db37bf1166937748c6Steve Block 1162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 1164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot()); 116559151504615d929945dc59db37bf1166937748c6Steve Block Register context = rsi; 116659151504615d929945dc59db37bf1166937748c6Steve Block Register temp = rbx; 116759151504615d929945dc59db37bf1166937748c6Steve Block 1168589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 116959151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (s->calls_non_strict_eval()) { 117159151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 117259151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 117359151504615d929945dc59db37bf1166937748c6Steve Block Immediate(0)); 117459151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 117559151504615d929945dc59db37bf1166937748c6Steve Block } 11763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 117759151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering rsi. 117859151504615d929945dc59db37bf1166937748c6Steve Block context = temp; 117959151504615d929945dc59db37bf1166937748c6Steve Block } 118059151504615d929945dc59db37bf1166937748c6Steve Block } 118159151504615d929945dc59db37bf1166937748c6Steve Block // Check that last extension is NULL. 118259151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); 118359151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 1184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This function is used only for loads, not stores, so it's safe to 1186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // return an rsi-based operand (the write barrier cannot be allowed to 1187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destroy the rsi register). 1188589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(context, var->index()); 118959151504615d929945dc59db37bf1166937748c6Steve Block} 119059151504615d929945dc59db37bf1166937748c6Steve Block 119159151504615d929945dc59db37bf1166937748c6Steve Block 1192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, 1193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TypeofState typeof_state, 1194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow, 1195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* done) { 119659151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast-case code for variables that might be shadowed by 119759151504615d929945dc59db37bf1166937748c6Steve Block // eval-introduced variables. Eval is used a lot without 119859151504615d929945dc59db37bf1166937748c6Steve Block // introducing variables. In those cases, we do not want to 119959151504615d929945dc59db37bf1166937748c6Steve Block // perform a runtime call for all variables in the scope 120059151504615d929945dc59db37bf1166937748c6Steve Block // containing the eval. 12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == DYNAMIC_GLOBAL) { 1202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 120359151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == DYNAMIC_LOCAL) { 1205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* local = var->local_if_not_shadowed(); 1206589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(rax, ContextSlotOperandCheckExtensions(local, slow)); 12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (local->mode() == CONST || 12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch local->mode() == CONST_HARMONY || 12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch local->mode() == LET) { 1210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1211589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(not_equal, done); 12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (local->mode() == CONST) { 12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { // LET || CONST_HARMONY 12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(var->name()); 12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 121859151504615d929945dc59db37bf1166937748c6Steve Block } 1219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(done); 122059151504615d929945dc59db37bf1166937748c6Steve Block } 122159151504615d929945dc59db37bf1166937748c6Steve Block} 122259151504615d929945dc59db37bf1166937748c6Steve Block 122359151504615d929945dc59db37bf1166937748c6Steve Block 12243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 12253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Record position before possible IC call. 12263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SetSourcePosition(proxy->position()); 12273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Variable* var = proxy->var(); 12283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Three cases: global variables, lookup variables, and all other types of 1230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // variables. 1231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 1232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: { 1233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "Global variable"); 1234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Use inline caching. Variable name is passed in rcx and the global 1235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // object on the stack. 1236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Move(rcx, var->name()); 1237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(rax, GlobalObjectOperand()); 1238589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(rax); 1241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 124359151504615d929945dc59db37bf1166937748c6Steve Block 1244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 1245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 1246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 1247589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); 12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->binding_needs_init()) { 12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // var->scope() may be NULL when the proxy is located in eval code and 12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // refers to a potential outside binding. Currently those bindings are 12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // always looked up dynamically, i.e. in that case 12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // var->location() == LOOKUP. 12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // always holds. 12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(var->scope() != NULL); 12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the binding really needs an initialization check. The check 12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // can be skipped in the following situation: we have a LET or CONST 12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding in harmony mode, both the Variable and the VariableProxy have 12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the same declaration scope (i.e. they are both in global code, in the 12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // same function or in the same eval code) and the VariableProxy is in 12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the source physically located after the initializer of the variable. 12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We cannot skip any initialization checks for CONST in non-harmony 12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // mode because const variables may be declared but never initialized: 12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // if (false) { const x; }; var y = x; 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The condition on the declaration scopes is a conservative check for 12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // nested functions that access a binding and are called before the 12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding is initialized: 12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function() { f(); let x = 1; function f() { x = 2; } } 12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool skip_init_check; 12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { 12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch skip_init_check = false; 12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that we always have valid source position. 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(var->initializer_position() != RelocInfo::kNoPosition); 12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(proxy->position() != RelocInfo::kNoPosition); 12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch skip_init_check = var->mode() != CONST && 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var->initializer_position() < proxy->position(); 12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!skip_init_check) { 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Let and const need a read barrier. 12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetVar(rax, var); 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &done, Label::kNear); 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == LET || var->mode() == CONST_HARMONY) { 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Throw a reference error when using an uninitialized let/const 12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding in harmony mode. 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(var->name()); 12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Uninitalized const bindings outside of harmony mode are unholed. 12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(var->mode() == CONST); 12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(rax); 13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1302589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1303589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(var); 1305589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1307d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1308589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: { 1309589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label done, slow; 1310589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Generate code for loading from variables potentially shadowed 1311589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // by eval-introduced variables. 1312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); 1313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 1314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "Lookup slot"); 1315589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(rsi); // Context. 131669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(var->name()); 1317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kLoadContextSlot, 2); 131869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&done); 131969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(rax); 1320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1326d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 1328bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label materialized; 13293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 13303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rdi = JS function. 1331bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rcx = literals array. 1332bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rbx = regexp literal. 1333bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rax = regexp literal clone. 13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1335bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 133780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1338bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rbx, FieldOperand(rcx, literal_offset)); 1339bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 1340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(not_equal, &materialized, Label::kNear); 1341bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 13423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create regexp literal using runtime function 13433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Result will be in rax. 1344bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(rcx); 13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->pattern()); 13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->flags()); 13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1349bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rbx, rax); 1350bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1351bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&materialized); 1352bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1353bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label allocated, runtime_allocate; 1354bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 1355bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&allocated); 1356bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1357bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&runtime_allocate); 1358bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(rbx); 1359bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Push(Smi::FromInt(size)); 1360bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1361bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(rbx); 1362bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1363bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&allocated); 1364bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Copy the content into the newly allocated memory. 1365bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // (Unroll copy loop once for better throughput). 1366bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 1367bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rdx, FieldOperand(rbx, i)); 1368bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); 1369bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, i), rdx); 1370bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, i + kPointerSize), rcx); 1371bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1372bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if ((size % (2 * kPointerSize)) != 0) { 1373bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); 1374bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, size - kPointerSize), rdx); 1375bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 13760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) { 13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expression == NULL) { 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kNullValueRootIndex); 13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(expression); 13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_properties = expr->constant_properties(); 1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(expr->literal_index())); 13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(constant_properties); 139644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int flags = expr->fast_elements() 139744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kFastElements 139844f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 139944f0eee88ff00398ff7f715fab053374d808c90dSteve Block flags |= expr->has_function() 140044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kHasFunction 140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 140244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(Smi::FromInt(flags)); 14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int properties_count = constant_properties->length() / 2; 1404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->depth() > 1) { 14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (flags != ObjectLiteral::kFastElements || 14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 140885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4); 14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowObjectStub stub(properties_count); 14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 1412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in rax. 1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 14183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Mark all computed expressions that are bound to a key that 14193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // is shadowed by a later occurrence of the same key. For the 14203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // marked expressions, no store code is emitted. 14213e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu expr->CalculateEmitStore(); 14223e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorTable accessor_table(isolate()->zone()); 1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Save result on the stack 1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::CONSTANT: 1436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 1437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 14423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1443053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block VisitForAccumulatorValue(value); 1444053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ Move(rcx, key->handle()); 1445053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block __ movq(rdx, Operand(rsp, 0)); 14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 14493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET, key->id()); 1450086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(key->id(), NO_REGISTERS); 1451053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } else { 1452053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block VisitForEffect(value); 14533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 1458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 14590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 14600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 14613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(NONE)); // PropertyAttributes 1463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallRuntime(Runtime::kSetProperty, 4); 14643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 14653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ Drop(3); 14663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 146885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch case ObjectLiteral::Property::GETTER: 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch accessor_table.lookup(key)->second->getter = value; 14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case ObjectLiteral::Property::SETTER: 14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch accessor_table.lookup(key)->second->setter = value; 1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Emit code to define accessors, using only a single call to the runtime for 14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // each pair of corresponding getters and setters. 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (AccessorTable::Iterator it = accessor_table.begin(); 14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch it != accessor_table.end(); 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++it) { 14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Operand(rsp, 0)); // Duplicate receiver. 14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(it->first); 14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->getter); 14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->setter); 14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(NONE)); 14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5); 14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 149044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (expr->has_function()) { 149144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result_saved); 149244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(Operand(rsp, 0)); 149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallRuntime(Runtime::kToFastProperties, 1); 149444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 14970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 14990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 15003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 15023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 15053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_elements = expr->constant_elements(); 15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(2, constant_elements->length()); 15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind constant_elements_kind = 15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_constant_fast_elements = constant_elements_kind == FAST_ELEMENTS; 15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArrayBase> constant_elements_values( 15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase::cast(constant_elements->get(1))); 1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 15173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(constant_elements); 15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap* heap = isolate()->heap(); 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (has_constant_fast_elements && 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch constant_elements_values->map() == heap->fixed_cow_array_map()) { 15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the elements are already FAST_ELEMENTS, the boilerplate cannot 15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // change, so it's possible to specialize the stub in advance. 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1); 1527756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub stub( 15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, 15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch length); 1530756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 1531756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (expr->depth() > 1) { 1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1533756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 1534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(constant_elements_kind == FAST_ELEMENTS || 15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch constant_elements_kind == FAST_SMI_ONLY_ELEMENTS || 15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FLAG_smi_only_arrays); 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the elements are already FAST_ELEMENTS, the boilerplate cannot 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // change, so it's possible to specialize the stub in advance. 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowArrayStub::Mode mode = has_constant_fast_elements 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? FastCloneShallowArrayStub::CLONE_ELEMENTS 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowArrayStub stub(mode, length); 1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 15513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 15533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 15543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 15553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 15563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 15573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 15583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 15623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 15633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 15643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 15663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (constant_elements_kind == FAST_ELEMENTS) { 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fast-case array literal with ElementsKind of FAST_ELEMENTS, they cannot 15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // transition and don't need to call the runtime stub. 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = FixedArray::kHeaderSize + (i * kPointerSize); 15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the subexpression value in the array's elements. 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rbx, offset), result_register()); 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier for the array store. 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rbx, offset, result_register(), rcx, 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch INLINE_SMI_CHECK); 15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the subexpression value in the array's elements. 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset)); 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rcx, Smi::FromInt(i)); 15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rdx, Smi::FromInt(expr->literal_index())); 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreArrayLiteralElementStub stub; 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1589086aeeaae12517475c22695a200be45495516549Ben Murdoch 1590086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 15913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 15940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 15960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 15973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1610402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 16113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 1612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 161480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 161580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (property != NULL) { 161680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen assign_type = (property->key()->IsPropertyName()) 161780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? NAMED_PROPERTY 161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : KEYED_PROPERTY; 1619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1620402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1623402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1624402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1625402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1626402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 16290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(property->obj()); 1630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1631402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 16320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1634402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1635086aeeaae12517475c22695a200be45495516549Ben Murdoch case KEYED_PROPERTY: { 1636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->is_compound()) { 16373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 16383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(property->key()); 1639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 0)); 1640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 1641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 16423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 16433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->key()); 1644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1645402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1646086aeeaae12517475c22695a200be45495516549Ben Murdoch } 1647402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 16498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // For compound assignments we need another deoptimization point after the 16508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // variable/property load. 1651402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 16520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 16530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 16540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 16553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->target()->AsVariableProxy()); 16568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailout(expr->target(), TOS_REG); 16570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 16580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 16590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 16608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); 16610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 16620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 16630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 16648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); 16650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 16660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1667402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 1670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(rax); // Left operand goes on the stack. 1671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForAccumulatorValue(expr->value()); 1672402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 167380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 167480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? OVERWRITE_RIGHT 167580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : NO_OVERWRITE; 167680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position() + 1); 16770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 167880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitInlineSmiBinaryOp(expr->binary_operation(), 168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mode, 168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 1683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch expr->value()); 168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBinaryOp(expr->binary_operation(), op, mode); 168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1687086aeeaae12517475c22695a200be45495516549Ben Murdoch // Deoptimization point in case the binary operation may have side effects. 1688086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailout(expr->binary_operation(), TOS_REG); 168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 16900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1693402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1694402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1696402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1697402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 17000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen expr->op()); 1701086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1705402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1708402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, key->handle()); 171844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 17193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ call(ic, RelocInfo::CODE_TARGET, prop->id()); 1720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1723d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 172544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ call(ic, RelocInfo::CODE_TARGET, prop->id()); 1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 173280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 173380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 1734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Expression* right) { 173580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Do combined smi check of the operands. Left operand is on the 173680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // stack (popped into rdx). Right operand is in rax but moved into 173780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx to make the shifts easier. 1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, stub_call, smi_case; 173980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ pop(rdx); 174080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rcx, rax); 17411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ or_(rax, rdx); 17421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); 174480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 174580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&stub_call); 17461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, rcx); 1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(op, mode); 17483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 17493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 175180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 175280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&smi_case); 175380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 175480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SAR: 175580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftArithmeticRight(rax, rdx, rcx); 175680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 175780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHL: 175880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftLeft(rax, rdx, rcx); 175980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 176080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHR: 176180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call); 176280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 176380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::ADD: 176480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiAdd(rax, rdx, rcx, &stub_call); 176580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 176680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SUB: 176780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiSub(rax, rdx, rcx, &stub_call); 176880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 176980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::MUL: 177080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiMul(rax, rdx, rcx, &stub_call); 177180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 177280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_OR: 177380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiOr(rax, rdx, rcx); 177480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 177580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_AND: 177680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiAnd(rax, rdx, rcx); 177780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 177880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_XOR: 177980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiXor(rax, rdx, rcx); 178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 178180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen default: 178280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UNREACHABLE(); 178380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 178480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 178580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 178680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 17870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 178880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 178980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 179080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Token::Value op, 179380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode) { 17941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(rdx); 1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(op, mode); 17963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 17973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 17983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 17990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1802e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 18123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 1813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 18250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 18260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(var, Token::ASSIGN); 1827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Preserve value. 18310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 1833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rax); // Restore value. 1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rcx, prop->key()->AsLiteral()->handle()); 18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 18363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 18383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic); 1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Preserve value. 18433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 18443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(prop->key()); 18453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rcx, rax); 18463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(rdx); 1847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ pop(rax); // Restore value. 18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->KeyedStoreIC_Initialize() 18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 18513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic); 1852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 1856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1859d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 18600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::Value op) { 1861589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 1862589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Global var, const, or let. 18633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Move(rcx, var->name()); 18648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(rdx, GlobalObjectOperand()); 18653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 18663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 18673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 18683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (op == Token::INIT_CONST) { 1870589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Const initializers need a write barrier. 1871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(!var->IsParameter()); // No const parameters. 1872589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsStackLocal()) { 1873589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label skip; 1874589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(rdx, StackOperand(var)); 1875589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1876589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(not_equal, &skip); 1877589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(StackOperand(var), rax); 1878589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&skip); 1879589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 1880589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot() || var->IsLookupSlot()); 1881589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Like var declarations, const declarations are hoisted to function 1882589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // scope. However, unlike var initializers, const initializers are 1883589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // able to drill a hole to that function context, even from inside a 1884589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 'with' context. We thus bypass the normal static scope lookup for 1885589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // var->IsContextSlot(). 1886589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(rax); 1887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(rsi); 1888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(var->name()); 1889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1890e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 18923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == LET && op != Token::INIT_LET) { 1893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Non-initializing assignment to let variable needs a write barrier. 1894589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsLookupSlot()) { 1895589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(rax); // Value. 1896589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(rsi); // Context. 1897589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(var->name()); 18983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(language_mode())); 1899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kStoreContextSlot, 4); 1900589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 1901589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 1902589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label assign; 1903589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, rcx); 1904589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(rdx, location); 1905589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1906589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(not_equal, &assign, Label::kNear); 1907589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(var->name()); 1908589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 1909589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&assign); 1910589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(location, rax); 1911589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 191269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(rdx, rax); 19133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot( 19143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); 191569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 191669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 19183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { 19193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assignment to var or initializing assignment to let/const 19203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in harmony mode. 1921589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsStackAllocated() || var->IsContextSlot()) { 1922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, rcx); 1923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (FLAG_debug_code && op == Token::INIT_LET) { 1924589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Check for an uninitialized let binding. 1925589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(rdx, location); 1926589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1927589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Check(equal, "Let binding re-initialization."); 1928589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1929589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Perform the assignment. 1930589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ movq(location, rax); 1931589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 1932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 19333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot( 19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); 19353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1936589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 1937589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsLookupSlot()); 1938589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(rax); // Value. 1939589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(rsi); // Context. 1940589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(var->name()); 19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(language_mode())); 1942589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kStoreContextSlot, 4); 19433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 19443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1945589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Non-initializing assignments to consts are ignored. 19463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 19473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 19483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1949d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 19543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, kPointerSize)); // Receiver is now under value. 1961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, prop->key()->AsLiteral()->handle()); 19684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (expr->ends_initialization_block()) { 19694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 19704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 19714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 19724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 19743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 19763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 1977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1978d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1979d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1981d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Drop(1); 1985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1986086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 1987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 1988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1991d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1992d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1995d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1996d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1997d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 2000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, 2 * kPointerSize)); 2001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 2002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 2003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rcx); 2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->ends_initialization_block()) { 2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. 2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 2012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->KeyedStoreIC_Initialize() 20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 20163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 2017d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2018d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 2019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 2021d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rdx); 2023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 2024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 2025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2026d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2027086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 20280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2029d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2030d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 2033d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 2034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 2035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2036e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 20370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->obj()); 2038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 2040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 20410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->obj()); 20420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->key()); 20437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(rdx); 2044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 2045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 2046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2050d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 2051402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Object> name, 2052e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 2053d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 2054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 20553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 20573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 20583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 20593e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 20603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ Move(rcx, name); 20613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 20643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 206544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = 2066589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); 20673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, mode, expr->id()); 2068086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordJSReturnSite(expr); 2069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 20710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 20759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Expression* key) { 20778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the key. 20788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(key); 20798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Swap the name of the function and the receiver on the stack to follow 20818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // the calling convention for call ICs. 20828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(rcx); 20838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(rax); 20848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(rcx); 20858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the arguments. 20879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ZoneList<Expression*>* args = expr->arguments(); 20889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int arg_count = args->length(); 2089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 20903e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 20913e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 20923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 20939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 20949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source position for debugger. 2095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 20969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call the IC initialization code. 209744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = 2098589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); 20998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. 21003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 2101086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordJSReturnSite(expr); 21029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Restore context register. 21039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 21048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang context()->DropAndPlug(1, rax); // Drop the key still on the stack. 21059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 21069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 21079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { 2109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 2110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 21133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 21143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 21153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 2118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 2119589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CallFunctionStub stub(arg_count, flags); 21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 2122086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordJSReturnSite(expr); 21233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 21243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 21253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Discard the function left on TOS. 21260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, rax); 2127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push copy of the first argument or undefined if it doesn't exist. 2132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (arg_count > 0) { 2133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Operand(rsp, arg_count * kPointerSize)); 2134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 2136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push the receiver of the enclosing function and do runtime call. 21393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize)); 2140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 21413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the language mode. 21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(language_mode())); 21433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the start position of the scope the calls resides in. 21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(scope()->start_position())); 2146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the runtime call. 21483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); 2149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 2153086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifdef DEBUG 2154086aeeaae12517475c22695a200be45495516549Ben Murdoch // We want to verify that RecordJSReturnSite gets called on all paths 2155086aeeaae12517475c22695a200be45495516549Ben Murdoch // through this function. Avoid early returns. 2156086aeeaae12517475c22695a200be45495516549Ben Murdoch expr->return_is_recorded_ = false; 2157086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif 2158086aeeaae12517475c22695a200be45495516549Ben Murdoch 2159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 2160589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Expression* callee = expr->expression(); 2161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = callee->AsVariableProxy(); 2162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Property* property = callee->AsProperty(); 2163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL && proxy->var()->is_possibly_eval()) { 2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 2166589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // resolve the function we need to call and the receiver of the call. 2167589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Then we call the resolved function using the given arguments. 2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 2170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope pos_scope(masm()->positions_recorder()); 2171589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(callee); 21723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. 2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21743e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push the arguments. 21753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 21763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 21773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2179589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Push a copy of the function (found below the arguments) and resolve 2180589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // eval. 2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); 21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitResolvePossiblyDirectEval(arg_count); 2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // The runtime call returns a pair of values in rax (function) and 21853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // rdx (receiver). Touch up the stack with the right values. 21863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 21873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 21883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 2190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 2191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT); 21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2194086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordJSReturnSite(expr); 2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 21970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, rax); 2198589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL && proxy->var()->IsUnallocated()) { 2199589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Call to a global variable. Push global object as receiver for the 2200589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // call IC lookup. 22018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(GlobalObjectOperand()); 2202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); 2203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 220459151504615d929945dc59db37bf1166937748c6Steve Block // Call to a lookup slot (dynamically introduced variable). 220559151504615d929945dc59db37bf1166937748c6Steve Block Label slow, done; 220659151504615d929945dc59db37bf1166937748c6Steve Block 2207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Generate code for loading from variables potentially shadowed by 2209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // eval-introduced variables. 2210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2211086aeeaae12517475c22695a200be45495516549Ben Murdoch } 2212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 2213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Call the runtime to find the function to call (returned in rax) and 2214589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // the object holding it (returned in rdx). 2215086aeeaae12517475c22695a200be45495516549Ben Murdoch __ push(context_register()); 2216589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(proxy->name()); 2217086aeeaae12517475c22695a200be45495516549Ben Murdoch __ CallRuntime(Runtime::kLoadContextSlot, 2); 2218086aeeaae12517475c22695a200be45495516549Ben Murdoch __ push(rax); // Function. 2219086aeeaae12517475c22695a200be45495516549Ben Murdoch __ push(rdx); // Receiver. 2220086aeeaae12517475c22695a200be45495516549Ben Murdoch 2221589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If fast case code has been generated, emit code to push the function 2222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // and receiver and have the slow path jump around this code. 2223086aeeaae12517475c22695a200be45495516549Ben Murdoch if (done.is_linked()) { 2224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call; 2225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&call, Label::kNear); 2226086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(&done); 2227086aeeaae12517475c22695a200be45495516549Ben Murdoch // Push function. 2228086aeeaae12517475c22695a200be45495516549Ben Murdoch __ push(rax); 2229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // The receiver is implicitly the global receiver. Indicate this by 2230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // passing the hole to the call function stub. 22313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ PushRoot(Heap::kTheHoleValueRootIndex); 2232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call); 223359151504615d929945dc59db37bf1166937748c6Steve Block } 223459151504615d929945dc59db37bf1166937748c6Steve Block 2235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // The receiver is either the global receiver or an object found by 2236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // LoadContextSlot. That object could be the hole if the receiver is 2237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // implicitly the global object. 2238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); 2239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (property != NULL) { 2240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->obj()); 2242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (property->key()->IsPropertyName()) { 2244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitCallWithIC(expr, 2245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch property->key()->AsLiteral()->handle(), 2246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch RelocInfo::CODE_TARGET); 2247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2248589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitKeyedCallWithIC(expr, property->key()); 2249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 22503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2251589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Call to an arbitrary expression not handled specially above. 2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(callee); 22543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 22568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(rbx, GlobalObjectOperand()); 2257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 2258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 2259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 2260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2261086aeeaae12517475c22695a200be45495516549Ben Murdoch 2262086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifdef DEBUG 2263086aeeaae12517475c22695a200be45495516549Ben Murdoch // RecordJSReturnSite should have been called. 2264086aeeaae12517475c22695a200be45495516549Ben Murdoch ASSERT(expr->return_is_recorded_); 2265086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif 2266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2269d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 2270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 2271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 2272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 2273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 2274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 227580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 227680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 227780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 22780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->expression()); 2279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 2281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 22840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 22853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 2288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 2289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 2290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 229180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into rdi and rax. 2292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(rax, arg_count); 229380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rdi, Operand(rsp, arg_count * kPointerSize)); 2294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record call targets in unoptimized code, but not in the snapshot. 22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallFunctionFlags flags; 22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!Serializer::enabled()) { 22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags = RECORD_CALL_TARGET; 22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> uninitialized = 23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TypeFeedbackCells::UninitializedSentinel(isolate()); 23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell(uninitialized); 23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordTypeFeedbackCell(expr->id(), cell); 23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, cell); 23053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags = NO_CALL_FUNCTION_FLAGS; 23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallConstructStub stub(flags); 23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); 23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 23120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 23133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 23143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 23153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 23163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 232580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 23260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 23270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_true); 2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { 23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 234680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 23470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 23480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2351f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); 2352f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Split(non_negative_smi, if_true, if_false, fall_through); 2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) { 23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 236780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 23680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 23690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kNullValueRootIndex); 2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_false); 2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 23803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, if_false); 23823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 23833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 238480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(below_equal, if_true, if_false, fall_through); 2385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { 23913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 23923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(args->length() == 1); 23933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 23940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 23953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 23963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 23973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 23983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 239980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 24000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 24010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 24023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 24033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ JumpIfSmi(rax, if_false); 24043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx); 24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 240680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(above_equal, if_true, if_false, fall_through); 24073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 24080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 24093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 24103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 24113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { 24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 242180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 24220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 24230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 243080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2436756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime* expr) { 24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2439756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ASSERT(args->length() == 1); 2440756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 24410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2442756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2443756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label materialize_true, materialize_false; 2444756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_true = NULL; 2445756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_false = NULL; 244680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 24470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 24480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2449756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 24508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (FLAG_debug_code) __ AbortIfSmi(rax); 24518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 24528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Check whether this map has already been checked to be safe for default 24538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // valueOf. 24548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 24558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ testb(FieldOperand(rbx, Map::kBitField2Offset), 24568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); 24578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(not_zero, if_true); 24588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 24598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Check for fast case object. Generate false result for slow case object. 24608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); 24618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 24628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); 24638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(equal, if_false); 24648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 24658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Look for valueOf symbol in the descriptor array, and indicate false if 24668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // found. The type is not checked, so if it is a transition it is a false 24678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // negative. 2468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadInstanceDescriptors(rbx, rbx); 24698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); 24708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // rbx: descriptor array 24718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // rcx: length of descriptor array 24728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Calculate the end of the descriptor array. 24738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); 24748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ lea(rcx, 24758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Operand( 24768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch rbx, index.reg, index.scale, FixedArray::kHeaderSize)); 24778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Calculate location of the first key name. 24788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ addq(rbx, 24798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Immediate(FixedArray::kHeaderSize + 24808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DescriptorArray::kFirstIndex * kPointerSize)); 24818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Loop through all the keys in the descriptor array. If one of these is the 24828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // symbol valueOf the result is false. 24838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Label entry, loop; 24848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(&entry); 24858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&loop); 24868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rdx, FieldOperand(rbx, 0)); 24878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Cmp(rdx, FACTORY->value_of_symbol()); 24888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(equal, if_false); 24898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ addq(rbx, Immediate(kPointerSize)); 24908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&entry); 24918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmpq(rbx, rcx); 24928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(not_equal, &loop); 24938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 24948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Reload map as register rbx was used as temporary above. 24958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 24968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 24978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // If a valueOf property is not found on the object check that it's 24988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // prototype is the un-modified String prototype. If not result is false. 24998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); 25008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ testq(rcx, Immediate(kSmiTagMask)); 25018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(zero, if_false); 25028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 25038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 25048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset)); 25058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmpq(rcx, 25068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 25078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(not_equal, if_false); 25088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Set the bit in the map to indicate that it has been checked safe for 25098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // default valueOf and set true result. 25108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ or_(FieldOperand(rbx, Map::kBitField2Offset), 25118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); 25128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(if_true); 25138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 25150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2516756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2517756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2518756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { 25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 252880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 25343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 253580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 25423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 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 __ JumpIfSmi(rax, if_false); 2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 25563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, 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 25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { 25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 257280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 25783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 257980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { 25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(expr->arguments()->length() == 0); 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 259280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 260144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset), 260244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &check_frame_marker); 2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 260844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset), 260944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::CONSTRUCT)); 26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 261180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { 26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 26220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 26230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 262880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 26290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 26300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rbx); 2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rax, rbx); 26343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 263580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) { 26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 264580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ArgumentsAccessStub expects the key in rdx and the formal 264680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // parameter count in rax. 26470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 26493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); 2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 26520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(expr->arguments()->length() == 0); 2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label exit; 2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 26613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); 2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 266544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), 266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &exit, Label::kNear); 2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (FLAG_debug_code) __ AbortIfNotSmi(rax); 26750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &null); 2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assume that there are only two callable types, and one of them is at 26923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // either end of the type range for JS object types. Saves extra comparisons. 26933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 26943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax); 26953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Map is now in rax. 2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, &null); 26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_SPEC_OBJECT_TYPE + 1); 26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &function); 27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); 27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAST_SPEC_OBJECT_TYPE - 1); 27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &function); 27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assume that there is no larger type. 27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); 27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the constructor in the map is a JS function. 2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, Map::kConstructorOffset)); 2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &non_function_constructor); 2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rax now contains the constructor function. Grab the 2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); 2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); 2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 272144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rax, isolate()->factory()->function_class_symbol()); 2722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 272644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rax, isolate()->factory()->Object_symbol()); 2727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kNullValueRootIndex); 2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLog(CallRuntime* expr) { 2741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 27510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 27520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 27570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) { 27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(expr->arguments()->length() == 0); 2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber); 2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 27713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Allocate a heap number. 27723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, rax); 2774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Return a random uint32 number in rax. 2778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. 27798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ PrepareCallCFunction(1); 27808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef _WIN64 27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, ContextOperand(context_register(), Context::GLOBAL_INDEX)); 27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); 27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#else 27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, ContextOperand(context_register(), Context::GLOBAL_INDEX)); 27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset)); 27878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 27888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); 2789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in rax to 0.(32 random bits) in a double 2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm1, rcx); 2795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm0, rax); 2796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cvtss2sd(xmm1, xmm1); 2797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm0, xmm1); 2798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ subsd(xmm0, xmm1); 2799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0); 2800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, rbx); 28020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) { 2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 28110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 28120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 28130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 28150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { 2820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 28223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 28240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 28250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 28260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 28270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(3)); 2828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 28290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) { 28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); // Load the object. 2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &done); 2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 2843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); 2844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, JSValue::kValueOffset)); 2846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 28480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) { 28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 28543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(args->length() == 2); 28553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_NE(NULL, args->at(1)->AsLiteral()); 28563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle())); 28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(args->at(0)); // Load the object. 28593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label runtime, done; 28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = rax; 28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = rax; 28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = rcx; 28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AbortIfSmi(object); 28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(object, JS_DATE_TYPE, scratch); 28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Trying to get date field from non-date."); 28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() == 0) { 28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, FieldOperand(object, JSDate::kValueOffset)); 28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() < JSDate::kFirstUncachedField) { 28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(scratch, stamp); 28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &runtime, Label::kNear); 28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, FieldOperand(object, JSDate::kValueOffset + 28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kPointerSize * index->value())); 28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 28833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime); 28843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(2); 28853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef _WIN64 28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, object); 28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdx, index, RelocInfo::NONE); 28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else 28893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, object); 28903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rsi, index, RelocInfo::NONE); 28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 28963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(rax); 28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 2901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 29040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 29050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 29063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathPowStub stub(MathPowStub::ON_STACK); 2907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 29080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { 29133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Load the object. 29170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); // Load the value. 291880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ pop(rbx); // rax = value. rbx = object. 2919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 2922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rbx, &done); 2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); 2926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 2929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax); 2930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 2931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 2932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); 2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 29360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { 29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 29450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 29490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { 29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 29607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(rax, rbx); 29617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 29627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 29657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 29680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rbx); 29697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 29707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 29717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 29747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 29757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 29760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 29770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 29787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 29797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 29807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 29817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rdx; 29827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 29837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 29847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 29857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 29867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 29877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 29887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 29897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 29907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 29917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 29927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 29937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 29947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 29957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 2996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 29997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 30007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 30017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 30027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 30037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 30057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move the undefined value into the result register, which will 30067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 30077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 30087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 30097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 30117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 30140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { 30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 30207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 30217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 30230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 30247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 30267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = rdx; 30287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rax; 30297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 30317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 30337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 30347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 30357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 30367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 30387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 30397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 30407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 30417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 30427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 30437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 30447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 30457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 30477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 30487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 30497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kEmptyStringRootIndex); 30507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 30517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 30537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 30547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 30557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(result, Smi::FromInt(0)); 30567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 30577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 30597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 30607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 30620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 3063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 30710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 30750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 30803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 3082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 30840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 30880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSin(CallRuntime* expr) { 3093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 3094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::SIN, 3095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::TAGGED); 30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 30980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 31000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathCos(CallRuntime* expr) { 3105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 3106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::COS, 3107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::TAGGED); 31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 31100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 31120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathTan(CallRuntime* expr) { 31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the argument on the stack and call the stub. 31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::TAN, 31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub::TAGGED); 31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 31213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(args->length() == 1); 31223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(args->at(0)); 31233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(rax); 31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathLog(CallRuntime* expr) { 3129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the argument on the stack and call the stub. 3130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::LOG, 3131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::TAGGED); 31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(args->length() == 1); 3134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForStackValue(args->at(0)); 3135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallStub(&stub); 3136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 3137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) { 3141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime function. 31423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 31440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sqrt, 1); 31460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { 31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 3153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int arg_count = args->length() - 2; // 2 ~ receiver and function. 3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < arg_count + 1; i++) { 3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForStackValue(args->at(i)); 3157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForAccumulatorValue(args->last()); // Function. 3159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for proxy. 31613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label proxy, done; 31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rax, JS_FUNCTION_PROXY_TYPE, rbx); 31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &proxy); 31643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // InvokeFunction requires the function in rdi. Move it in there. 3166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rdi, result_register()); 3167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 3168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(rdi, count, CALL_FUNCTION, 3169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 3170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 31713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 31723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&proxy); 31743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rax); 31753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kCall, args->length()); 31763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 31773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RegExpConstructResultStub stub; 31843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 31860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 31870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 31880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 3189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallStub(&stub); 31900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 31953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 3197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 3200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 320244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->global_context()->jsfunction_result_caches()); 3203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 3204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 3205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 32060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = rax; 3213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = rbx; 3214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register tmp = rcx; 321559151504615d929945dc59db37bf1166937748c6Steve Block __ movq(cache, ContextOperand(rsi, Context::GLOBAL_INDEX)); 3216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 3217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, GlobalObject::kGlobalContextOffset)); 3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 321959151504615d929945dc59db37bf1166937748c6Steve Block ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 3221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, not_found; 3224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 322569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 3227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SmiIndex index = 3228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2); 3229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(key, FieldOperand(cache, 3230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 3231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 3232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize)); 3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, ¬_found, Label::kNear); 3234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(cache, 3235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 3236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 3237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize + kPointerSize)); 3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 3241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 3242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(cache); 3243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(key); 3244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 3245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 32470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { 32523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3253bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT_EQ(2, args->length()); 3254bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3255bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register right = rax; 3256bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register left = rbx; 3257bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp = rcx; 3258bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 32590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 32600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3261bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(left); 3262bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, fail, ok; 3264bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(left, right); 3265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &ok, Label::kNear); 3266bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Fail if either is a non-HeapObject. 3267bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Condition either_smi = masm()->CheckEitherSmi(left, right, tmp); 3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(either_smi, &fail, Label::kNear); 3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &fail, Label::kNear); 3270bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset)); 3271bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset), 3272bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Immediate(JS_REGEXP_TYPE)); 3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &fail, Label::kNear); 3274bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset)); 3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &fail, Label::kNear); 3276bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset)); 3277bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset)); 3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &ok, Label::kNear); 3279bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&fail); 328044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rax, isolate()->factory()->false_value()); 3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3282bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&ok); 328344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rax, isolate()->factory()->true_value()); 3284bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&done); 3285bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 32860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3287bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 3288bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3289bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 329280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(args->length() == 1); 329380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 32940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 329580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 329680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 329780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 329880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 329980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 33000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 33010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 330280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 330380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testl(FieldOperand(rax, String::kHashFieldOffset), 330480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(String::kContainsCachedArrayIndexMask)); 33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 330680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, if_true); 330780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(if_false); 330880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 33090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 331080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 331180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 331280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 33133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { 33143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 331580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(args->length() == 1); 33160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 331780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) { 3319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AbortIfNotString(rax); 3320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 332280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); 332380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(String::kHashShift >= kSmiTagSize); 332480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(rax, rax); 332580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 33260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 332780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 332880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 332980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 33303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { 333144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label bailout, return_result, done, one_char_separator, long_separator, 333244f0eee88ff00398ff7f715fab053374d808c90dSteve Block non_trivial_array, not_size_one_array, loop, 333344f0eee88ff00398ff7f715fab053374d808c90dSteve Block loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; 33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 333544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(args->length() == 2); 333644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We will leave the separator on the stack until the end of the function. 333744f0eee88ff00398ff7f715fab053374d808c90dSteve Block VisitForStackValue(args->at(1)); 333844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Load this to rax (= array) 333944f0eee88ff00398ff7f715fab053374d808c90dSteve Block VisitForAccumulatorValue(args->at(0)); 334044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // All aliases of the same register have disjoint lifetimes. 334144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register array = rax; 334244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register elements = no_reg; // Will be rax. 334344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 334444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register index = rdx; 334544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 334644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register string_length = rcx; 334744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register string = rsi; 334944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 335044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch = rbx; 335144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 335244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register array_length = rdi; 335344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result_pos = no_reg; // Will be rdi. 335444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 335544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand separator_operand = Operand(rsp, 2 * kPointerSize); 335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand result_operand = Operand(rsp, 1 * kPointerSize); 335744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand array_length_operand = Operand(rsp, 0 * kPointerSize); 335844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Separator operand is already pushed. Make room for the two 335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // other stack fields, and clear the direction flag in anticipation 336044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // of calling CopyBytes. 336144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ subq(rsp, Immediate(2 * kPointerSize)); 336244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cld(); 336344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the array is a JSArray 336444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(array, &bailout); 336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &bailout); 336744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 336844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the array has fast elements. 33693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CheckFastElements(scratch, &bailout); 337044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 337144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Array has fast elements, so its length must be a smi. 337244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the array has length zero, return the empty string. 337344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset)); 337444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiCompare(array_length, Smi::FromInt(0)); 337544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_zero, &non_trivial_array); 337644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(rax, Heap::kEmptyStringRootIndex); 337744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&return_result); 337844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 337944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Save the array length on the stack. 338044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&non_trivial_array); 338144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(array_length, array_length); 338244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(array_length_operand, array_length); 338344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 338444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Save the FixedArray containing array's elements. 338544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // End of array's live range. 338644f0eee88ff00398ff7f715fab053374d808c90dSteve Block elements = array; 338744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(elements, FieldOperand(array, JSArray::kElementsOffset)); 338844f0eee88ff00398ff7f715fab053374d808c90dSteve Block array = no_reg; 338944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 339044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that all array elements are sequential ASCII strings, and 339244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // accumulate the sum of their lengths, as a smi-encoded value. 339344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, 0); 339444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(string_length, 0); 339544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loop condition: while (index < array_length). 339644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live loop registers: index(int32), array_length(int32), string(String*), 339744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch, string_length(int32), elements(FixedArray*). 339844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_debug_code) { 339944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpq(index, array_length); 340044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Assert(below, "No empty arrays here in EmitFastAsciiArrayJoin"); 340144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 340244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop); 340344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(string, FieldOperand(elements, 340444f0eee88ff00398ff7f715fab053374d808c90dSteve Block index, 340544f0eee88ff00398ff7f715fab053374d808c90dSteve Block times_pointer_size, 340644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 340744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(string, &bailout); 340844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset)); 340944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 341044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ andb(scratch, Immediate( 341144f0eee88ff00398ff7f715fab053374d808c90dSteve Block kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 341244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpb(scratch, Immediate(kStringTag | kAsciiStringTag | kSeqStringTag)); 341344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &bailout); 341444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ AddSmiField(string_length, 341544f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, SeqAsciiString::kLengthOffset)); 341644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(overflow, &bailout); 341744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incl(index); 341844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(index, array_length); 341944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(less, &loop); 342044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 342144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live registers: 342244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string_length: Sum of string lengths. 342344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: FixedArray of strings. 342444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: Array length. 342544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // array_length: Array length. 342644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 342744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If array_length is 1, return elements[0], a string. 342844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(array_length, Immediate(1)); 342944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, ¬_size_one_array); 343044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rax, FieldOperand(elements, FixedArray::kHeaderSize)); 343144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&return_result); 343244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 343344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(¬_size_one_array); 343444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 343544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // End of array_length live range. 343644f0eee88ff00398ff7f715fab053374d808c90dSteve Block result_pos = array_length; 343744f0eee88ff00398ff7f715fab053374d808c90dSteve Block array_length = no_reg; 343844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 343944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live registers: 344044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string_length: Sum of string lengths. 344144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: FixedArray of strings. 344244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: Array length. 344344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 344444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the separator is a sequential ASCII string. 344544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(string, separator_operand); 344644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(string, &bailout); 344744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset)); 344844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 344944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ andb(scratch, Immediate( 345044f0eee88ff00398ff7f715fab053374d808c90dSteve Block kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 345144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpb(scratch, Immediate(kStringTag | kAsciiStringTag | kSeqStringTag)); 345244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &bailout); 345344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 345444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live registers: 345544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string_length: Sum of string lengths. 345644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: FixedArray of strings. 345744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: Array length. 345844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string: Separator string. 345944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 346044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Add (separator length times (array_length - 1)) to string_length. 346144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(scratch, 346244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, SeqAsciiString::kLengthOffset)); 346344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ decl(index); 346444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ imull(scratch, index); 346544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(overflow, &bailout); 346644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ addl(string_length, scratch); 346744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(overflow, &bailout); 346844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 346944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live registers and stack values: 347044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string_length: Total length of result string. 347144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: FixedArray of strings. 347244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ AllocateAsciiString(result_pos, string_length, scratch, 347344f0eee88ff00398ff7f715fab053374d808c90dSteve Block index, string, &bailout); 347444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(result_operand, result_pos); 347544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize)); 347644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 347744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(string, separator_operand); 347844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiCompare(FieldOperand(string, SeqAsciiString::kLengthOffset), 347944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(1)); 348044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(equal, &one_char_separator); 348144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(greater, &long_separator); 348244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 348344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 348444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Empty separator case: 348544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, 0); 348644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(scratch, array_length_operand); 348744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&loop_1_condition); 348844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loop condition: while (index < array_length). 348944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_1); 349044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Each iteration of the loop concatenates one string to the result. 349144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live values in registers: 349244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: which element of the elements array we are adding to the result. 349344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result_pos: the position to which we are currently copying characters. 349444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: the FixedArray of strings we are joining. 349544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch: array length. 349644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 349744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get string = array[index]. 349844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(string, FieldOperand(elements, index, 349944f0eee88ff00398ff7f715fab053374d808c90dSteve Block times_pointer_size, 350044f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 350144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(string_length, 350244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, String::kLengthOffset)); 350344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(string, 350444f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, SeqAsciiString::kHeaderSize)); 350544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CopyBytes(result_pos, string, string_length); 350644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incl(index); 350744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_1_condition); 350844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(index, scratch); 350944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(less, &loop_1); // Loop while (index < array_length). 351044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&done); 351144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 351244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Generic bailout code used from several places. 351344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&bailout); 351444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 351544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&return_result); 351644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 351744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 351844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // One-character separator case 351944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&one_char_separator); 35203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the separator ASCII character value. 352144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Register "string" holds the separator. 352244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movzxbl(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize)); 352344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, 0); 352444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Jump into the loop after the code that copies the separator, so the first 352544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // element is not preceded by a separator 352644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&loop_2_entry); 352744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loop condition: while (index < length). 352844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_2); 352944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Each iteration of the loop concatenates one string to the result. 353044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live values in registers: 353144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: The FixedArray of strings we are joining. 353244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: which element of the elements array we are adding to the result. 353344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result_pos: the position to which we are currently copying characters. 353444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch: Separator character. 353544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 353644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Copy the separator character to the result. 353744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movb(Operand(result_pos, 0), scratch); 353844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incq(result_pos); 353944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 354044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_2_entry); 354144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get string = array[index]. 354244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(string, FieldOperand(elements, index, 354344f0eee88ff00398ff7f715fab053374d808c90dSteve Block times_pointer_size, 354444f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 354544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(string_length, 354644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, String::kLengthOffset)); 354744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(string, 354844f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, SeqAsciiString::kHeaderSize)); 354944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CopyBytes(result_pos, string, string_length); 355044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incl(index); 355144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(index, array_length_operand); 355244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(less, &loop_2); // End while (index < length). 355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&done); 355444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 355544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 355644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Long separator case (separator is more than one character). 355744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&long_separator); 355844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Make elements point to end of elements array, and index 356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // count from -array_length to zero, so we don't need to maintain 356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // a loop limit. 356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(index, array_length_operand); 356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(elements, FieldOperand(elements, index, times_pointer_size, 356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ neg(index); 356644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 356744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Replace separator string with pointer to its first character, and 356844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // make scratch be its length. 356944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(string, separator_operand); 357044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(scratch, 357144f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, String::kLengthOffset)); 357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(string, 357344f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, SeqAsciiString::kHeaderSize)); 357444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(separator_operand, string); 357544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 357644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Jump into the loop after the code that copies the separator, so the first 357744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // element is not preceded by a separator 357844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&loop_3_entry); 357944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loop condition: while (index < length). 358044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_3); 358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Each iteration of the loop concatenates one string to the result. 358244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live values in registers: 358344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: which element of the elements array we are adding to the result. 358444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result_pos: the position to which we are currently copying characters. 358544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch: Separator length. 358644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // separator_operand (rsp[0x10]): Address of first char of separator. 358744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 358844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Copy the separator to the result. 358944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(string, separator_operand); 359044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(string_length, scratch); 359144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CopyBytes(result_pos, string, string_length, 2); 359244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 359344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_3_entry); 359444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get string = array[index]. 359544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(string, Operand(elements, index, times_pointer_size, 0)); 359644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(string_length, 359744f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, String::kLengthOffset)); 359844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(string, 359944f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, SeqAsciiString::kHeaderSize)); 360044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CopyBytes(result_pos, string, string_length); 360144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incq(index); 360244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &loop_3); // Loop while (index < 0). 360344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 360444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 360544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rax, result_operand); 360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 360744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&return_result); 360844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Drop temp values from the stack, and restore context register. 360944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ addq(rsp, Immediate(3 * kPointerSize)); 361044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 361144f0eee88ff00398ff7f715fab053374d808c90dSteve Block context()->Plug(rax); 36128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 36138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 36148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 3615d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 3617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 3618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 3619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 3620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 36243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 36253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 3627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 36288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(rax, GlobalObjectOperand()); 3629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 3630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 36313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 36323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 36333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 36343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 36350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 3636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 3639402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Call the JS runtime function using a call IC. 3640402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Move(rcx, expr->name()); 3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 364244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = 3643589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); 36443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, mode, expr->id()); 3645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 3646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 3648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 3649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 36500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3654d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 3657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3658589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Property* property = expr->expression()->AsProperty(); 3659589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 3660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3661589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (property != NULL) { 3662589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->obj()); 3663589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->key()); 36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) 36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? kNonStrictMode : kStrictMode; 36663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(strict_mode_flag)); 366769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 366869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(rax); 3669589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 3670589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 3671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Delete of an unqualified identifier is disallowed in strict mode 3672589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // but "delete this" is allowed. 36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); 3674589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 3675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(GlobalObjectOperand()); 3676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(var->name()); 3677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(kNonStrictMode)); 3678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(rax); 3680589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (var->IsStackAllocated() || var->IsContextSlot()) { 3681589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Result of deleting non-global variables is false. 'this' is 3682589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // not really a variable, though we implement it as one. The 3683589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // subexpression does not have side effects. 3684589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(var->is_this()); 3685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Non-global variable. Call the runtime to try to delete from the 3687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // context where the variable was introduced. 3688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(context_register()); 3689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(var->name()); 3690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallRuntime(Runtime::kDeleteContextSlot, 2); 3691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(rax); 3692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 36931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-property, non-variable reference is true. 3695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression may have side effects. 3696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 3697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(true); 3698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 3700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 3703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 3704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 37050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Heap::kUndefinedValueRootIndex); 3706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 3710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (context()->IsEffect()) { 3712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Unary NOT has no side effects so it's only necessary to visit the 3713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // subexpression. Match the optimizing compiler by not branching. 3714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context()->IsTest()) { 37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const TestContext* test = TestContext::cast(context()); 37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The labels are swapped for the recursive call. 37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->false_label(), 37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->true_label(), 37213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->fall_through()); 37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(test->true_label(), test->false_label()); 3723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We handle value contexts explicitly rather than simply visiting 37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for control and plugging the control flow into the context, 37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // because we need to prepare a pair of extra administrative AST ids 37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for the optimizing compiler. 37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); 37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false, done; 37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_false, 37323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true, 37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true); 37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_true); 37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); 37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsAccumulatorValue()) { 37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kTrueValueRootIndex); 37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kTrueValueRootIndex); 37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_false); 37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); 37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsAccumulatorValue()) { 37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kFalseValueRootIndex); 37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kFalseValueRootIndex); 37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 3750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 3755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 37560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { StackValueContext context(this); 37570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 37580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 37600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3764d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 3765d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 37660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label no_conversion; 37683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(result_register(), &no_conversion); 37691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ToNumberStub convert_stub; 37701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallStub(&convert_stub); 3771d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 37720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result_register()); 3773d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 3774d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3775d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 3777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitUnaryOperation(expr, "[ UnaryOperation (SUB)"); 37784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 37794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_NOT: 3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)"); 37824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 37834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 3784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 37863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 37873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 37883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 37893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr, 3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* comment) { 3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO(svenpanne): Allowing format strings in Comment would be nice here... 3793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Comment cmt(masm_, comment); 3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 3795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UnaryOverwriteMode overwrite = 3796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UnaryOpStub stub(expr->op(), overwrite); 3798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // UnaryOpStub expects the argument to be in the 3799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // accumulator register rax. 3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForAccumulatorValue(expr->expression()); 3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SetSourcePosition(expr->position()); 38023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 3803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context()->Plug(rax); 3804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 3808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Comment cmnt(masm_, "[ CountOperation"); 380980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 3810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand-sides are rewritten to have a 'throw 3812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' as the left-hand side. 3813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 3814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 3815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 38193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 3820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 3822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 3823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 3824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 3825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 3826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 3827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 3831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 3832e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 38330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 38343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->expression()->AsVariableProxy()); 3835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 3836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 38370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 3838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Smi::FromInt(0)); 3839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 38410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 38427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(rax); // Copy of receiver, needed for later store. 3843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 3844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 38453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 38463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(prop->key()); 38477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 38487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(rax); // Copy of key, needed for later store. 3849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 3850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3853086aeeaae12517475c22695a200be45495516549Ben Murdoch // We need a second deoptimization point after loading the value 3854086aeeaae12517475c22695a200be45495516549Ben Murdoch // in case evaluating the property load my have a side effect. 38558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (assign_type == VARIABLE) { 38568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailout(expr->expression(), TOS_REG); 38578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 38588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailoutForId(expr->CountId(), TOS_REG); 38598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3860086aeeaae12517475c22695a200be45495516549Ben Murdoch 3861d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 3862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label no_conversion; 38633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(rax, &no_conversion, Label::kNear); 38641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ToNumberStub convert_stub; 38651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallStub(&convert_stub); 3866d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 3867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 3869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 38700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 38710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 38720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 38730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 38740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 38750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 38760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(rax); 38770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 38780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 38790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(Operand(rsp, kPointerSize), rax); 38800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 38810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 38820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(Operand(rsp, 2 * kPointerSize), rax); 38830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 38840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 3889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, stub_call; 38901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 38911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 389280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(expr->op())) { 3893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 3894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 3895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 3896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 3897d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(overflow, &stub_call, Label::kNear); 3899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 3900d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 3901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfSmi(rax, &done, Label::kNear); 39021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 3904d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 3905d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 3906d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 3907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 3908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 3909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Record position before stub call. 3913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 3916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); 39171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (expr->op() == Token::INC) { 39181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rdx, Smi::FromInt(1)); 39191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 39201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rdx, rax); 39211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rax, Smi::FromInt(1)); 39221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 39233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); 39243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 3925d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 3926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in rax. 3928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 3929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 3930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 3931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 39320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 39330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 39340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 3935086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context.Plug(rax); 39370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 3939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 39400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 39410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 3945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 39460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 3947086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 3949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 3952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, prop->key()->AsLiteral()->handle()); 39534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 39543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 39553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 39563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 39573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 3958086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 39600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 39610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 39640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3968e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 3969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rcx); 3970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 39713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 39723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->KeyedStoreIC_Initialize() 39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 39743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 3975086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 39770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 39780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 39810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 39890d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 399080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VariableProxy* proxy = expr->AsVariableProxy(); 39910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsEffect()); 39920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsTest()); 39930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL && proxy->var()->IsUnallocated()) { 399580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Comment cmnt(masm_, "Global variable"); 399680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Move(rcx, proxy->name()); 39978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(rax, GlobalObjectOperand()); 399844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 399980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Use a regular load, not a contextual load, to avoid a reference 400080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // error. 40013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic); 4002086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailout(expr, TOS_REG); 40030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4004589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 400559151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 400659151504615d929945dc59db37bf1166937748c6Steve Block 400759151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 400859151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 4009589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 401059151504615d929945dc59db37bf1166937748c6Steve Block 401159151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 401280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(rsi); 401380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Push(proxy->name()); 401480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4015086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailout(expr, TOS_REG); 401659151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 401759151504615d929945dc59db37bf1166937748c6Steve Block 40180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 402080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // This expression cannot throw a reference error at the top level. 40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitInDuplicateContext(expr); 402280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 402380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 402480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 402580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 40263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> check) { 40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false; 40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_true = NULL; 40313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_false = NULL; 40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fall_through = NULL; 40333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &if_true, &if_false, &fall_through); 40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForTypeofValue(sub_expr); 40380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 40400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 404144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (check->Equals(isolate()->heap()->number_symbol())) { 4042e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_true); 404380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 404480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 404580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 404644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->string_symbol())) { 4047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 404880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 4050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(above_equal, if_false); 405180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 405280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 4053e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(zero, if_true, if_false, fall_through); 405444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->boolean_symbol())) { 405580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kTrueValueRootIndex); 4056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 405780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kFalseValueRootIndex); 405880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 405969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (FLAG_harmony_typeof && 406069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch check->Equals(isolate()->heap()->null_symbol())) { 406169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(rax, Heap::kNullValueRootIndex); 406269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Split(equal, if_true, if_false, fall_through); 406344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->undefined_symbol())) { 406480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 4065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 4066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 406780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 406880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 406980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 407080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 407180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 407244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->function_symbol())) { 4073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 40743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 40753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); 40763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, if_true); 40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE); 40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Split(equal, if_true, if_false, fall_through); 407944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->object_symbol())) { 4080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 408169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (!FLAG_harmony_typeof) { 408269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(rax, Heap::kNullValueRootIndex); 408369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, if_true); 408469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 40853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx); 4086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(below, if_false); 40873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 40883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above, if_false); 408980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 409080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 4091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 4092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(zero, if_true, if_false, fall_through); 409380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 409480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 4095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 40963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(if_true, if_false); 4097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 4098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4100d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 4101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 410280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 4103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 41043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First we try a fast inlined version of the compare when one of 41053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the operands is a literal. 41063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryLiteralCompare(expr)) return; 41073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 4109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 4110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 4111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 4112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 411380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 41140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 41150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 411680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 41173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Token::Value op = expr->op(); 41180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 411980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 4120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 41210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 4122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 41233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 4124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CompareRoot(rax, Heap::kTrueValueRootIndex); 412580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 4126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 41273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 41290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 4130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InstanceofStub stub(InstanceofStub::kNoFlags); 4131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 41323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 413480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns 0 for true. 413580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(zero, if_true, if_false, fall_through); 4136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 41400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 4141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = no_condition; 414280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 4143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 414480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::EQ: 4145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = equal; 4146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 4148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 4149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 41513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cc = greater; 4152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 41543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cc = less_equal; 4155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 4157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 4158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 4160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 4161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 4162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 4163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 41643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(rdx); 4165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 41660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 41671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 41680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 4169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_case; 41701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rcx, rdx); 41711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ or_(rcx, rax); 4172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 41731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpq(rdx, rax); 417480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, NULL); 417580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 417680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 4177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 41781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position and call the compare IC. 41791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetSourcePosition(expr->position()); 41801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Code> ic = CompareIC::GetUninitialized(op); 41813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 41823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 4183086aeeaae12517475c22695a200be45495516549Ben Murdoch 41843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 418680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, fall_through); 4187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 41883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 41893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 4191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 41920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 4193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 41963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NilValue nil) { 419980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 420080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 420180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 420280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 42030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 42040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 420580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(sub_expr); 42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex nil_value = nil == kNullValue ? 42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kNullValueRootIndex : 42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kUndefinedValueRootIndex; 42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rax, nil_value); 42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->op() == Token::EQ_STRICT) { 421380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 421480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex other_nil_value = nil == kNullValue ? 42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kUndefinedValueRootIndex : 42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kNullValueRootIndex; 421880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rax, other_nil_value); 422080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 42213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(rax, if_false); 422280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // It can be an undetectable object. 422380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 422480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 422580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 422680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 422780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 42280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 422980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 423080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 423180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 4232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 42340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 42380d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 42390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return rax; 42400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 42430d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 42440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return rsi; 42450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 42460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 42470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4248d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(IsAligned(frame_offset, kPointerSize)); 4250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, frame_offset), value); 42513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 42523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 42533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 425559151504615d929945dc59db37bf1166937748c6Steve Block __ movq(dst, ContextOperand(rsi, context_index)); 4256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 42593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 42603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Scope* declaration_scope = scope()->DeclarationScope(); 42613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (declaration_scope->is_global_scope()) { 42623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Contexts nested in the global context have a canonical empty function 42633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // as their closure, not the anonymous closure containing the global 42643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Pass a smi sentinel and let the runtime look up the empty 42653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // function. 42663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Push(Smi::FromInt(0)); 42673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (declaration_scope->is_eval_scope()) { 42683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Contexts created by a call to eval have the same closure as the 42693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // context calling eval, not the anonymous closure containing the eval 42703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Fetch it from the context. 42713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(ContextOperand(rsi, Context::CLOSURE_INDEX)); 42723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 42733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(declaration_scope->is_function_scope()); 42743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 42753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 42763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 42773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 42783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 4280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 4281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4283d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 4284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 4285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 4286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address on top of stack (smi encoded Code* delta) 42873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(rdx); 4288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 4289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subq(rdx, rcx); 4290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Integer32ToSmi(rdx, rdx); 42913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(rdx); 4292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 4293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 4294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4297d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 4298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 4299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 4300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 4301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address. 43023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(rdx); 4303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiToInteger32(rdx, rdx); 4304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 4305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ addq(rdx, rcx); 43063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(rdx); 4307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 4308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __ 4311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 431269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm()) 431369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 431469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 431569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int* stack_depth, 431669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int* context_length) { 431769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // The macros used here must preserve the result register. 431869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 431969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Because the handler block contains the context of the finally 432069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // code, we can restore it directly from there for the finally code 432169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // rather than iteratively unwinding contexts via their previous 432269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // links. 432369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Drop(*stack_depth); // Down to the handler block. 432469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (*context_length > 0) { 432569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Restore the context to its dedicated register and the stack. 432669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(rsi, Operand(rsp, StackHandlerConstants::kContextOffset)); 432769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 432869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 432969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ PopTryHandler(); 433069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ call(finally_entry_); 433169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 433269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch *stack_depth = 0; 433369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch *context_length = 0; 433469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return previous_; 433569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 433669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 433769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 433869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __ 4339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 43403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 4341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 4343