full-codegen-x64.cc revision f87a203d89e1bbb6708282e0b64dbd13d59b723d
14515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// Copyright 2010 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" 333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.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" 393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the 473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them. The actual argument count matches the 483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function. 493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rdi: the JS function object being called (ie, ourselves) 523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsi: our context 533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rbp: our caller's frame pointer 543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsp: stack pointer (pointing to return address) 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout. 58756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::Generate(CompilationInfo* info) { 593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(info_ == NULL); 603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu info_ = info; 613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 64f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG 65f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (strlen(FLAG_stop_at) > 0 && 66f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 67f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ int3(); 68f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 69f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif 70756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rbp); // Caller's frame pointer. 71756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(rbp, rsp); 72756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rsi); // Callee's context. 73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdi); // Callee's JS Function. 74756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int locals_count = scope()->num_stack_slots(); 77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (locals_count == 1) { 78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ PushRoot(Heap::kUndefinedValueRootIndex); 79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (locals_count > 1) { 80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < locals_count; i++) { 82756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdx); 83d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 84d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 85756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 86d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 87756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bool function_in_register = true; 884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 89756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 90756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 91756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots > 0) { 92756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate local context"); 93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Argument to NewContext is the function, which is still in rdi. 94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdi); 95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots <= FastNewContextStub::kMaximumSlots) { 96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastNewContextStub stub(heap_slots); 97756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 98756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 99756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallRuntime(Runtime::kNewContext, 1); 100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick function_in_register = false; 102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Context is returned in both rax and rsi. It replaces the context 103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // passed to us. It's saved in the stack and kept live in rsi. 104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy any necessary parameters into the context. 107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int num_parameters = scope()->num_parameters(); 108756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < num_parameters; i++) { 1090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = scope()->parameter(i)->AsSlot(); 110756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (slot != NULL && slot->type() == Slot::CONTEXT) { 111756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int parameter_offset = StandardFrameConstants::kCallerSPOffset + 112756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick (num_parameters - 1 - i) * kPointerSize; 113756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load parameter from stack. 114756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(rax, Operand(rbp, parameter_offset)); 115756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 116756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int context_offset = Context::SlotOffset(slot->index()); 117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(Operand(rsi, context_offset), rax); 118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Update the write barrier. This clobbers all involved 119756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // registers, so we have use a third register to avoid 120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // clobbering rsi. 121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(rcx, rsi); 122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ RecordWrite(rcx, context_offset, rax, rbx); 123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 125756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 1263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate an arguments object. 1280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Variable* arguments = scope()->arguments(); 129756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (arguments != NULL) { 130756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments object must be allocated after the context object, in 131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // case the "arguments" or ".arguments" variables are in the context. 132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate arguments object"); 133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (function_in_register) { 134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdi); 135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The receiver is just before the parameters on the caller's stack. 139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int offset = scope()->num_parameters() * kPointerSize; 140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ lea(rdx, 141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(rdx); 143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ Push(Smi::FromInt(scope()->num_parameters())); 144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments to ArgumentsAccessStub: 145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // function, receiver address, parameter count. 146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The stub will rewrite receiver and parameter count if the previous 147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // stack frame was an arguments adapter frame. 148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store new arguments object in both "arguments" and ".arguments" slots. 151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ movq(rcx, rax); 1520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Move(arguments->AsSlot(), rax, rbx, rdx); 1530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); 154756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Move(dot_arguments_slot, rcx, rbx, rdx); 155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke { Comment cmnt(masm_, "[ Declarations"); 158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // For named function expressions, declare the function name as a 159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant. 160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && scope()->function() != NULL) { 161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(scope()->function(), Variable::CONST, NULL); 162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Visit all the explicit declarations unless there is an illegal 164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // redeclaration. 165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->HasIllegalRedeclaration()) { 166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke scope()->VisitIllegalRedeclaration(this); 167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitDeclarations(scope()->declarations()); 169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Stack check"); 1730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel ok; 1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &ok); 1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block StackCheckStub stub; 1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallStub(&stub); 1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&ok); 1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceEnter, 0); 1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Body"); 186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu VisitStatements(function()->body()); 188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit a 'return undefined' in case control fell off the end of the body. 1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 2053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 2063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 2073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 214bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ RecordJSReturn(); 2163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Do not use the leave instruction here because it is too short to 2173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // patch with the code required by the debugger. 2183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsp, rbp); 2193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(rbp); 2203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ ret((scope()->num_parameters() + 1) * kPointerSize); 2213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Add padding that will be overwritten by a debugger breakpoint. We 2233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 2243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // (3 + 1 + 3). 225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const int kPadding = Assembler::kJSReturnSequenceLength - 7; 2263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < kPadding; ++i) { 2273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block masm_->int3(); 2283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check that the size of the code used for returning matches what is 230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expected by the debugger. 231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(Assembler::kJSReturnSequenceLength, 232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 2333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif 2343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 2363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 23880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenFullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( 23980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, Expression* left, Expression* right) { 24080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(ShouldInlineSmiCase(op)); 24180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return kNoConstants; 24280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 24380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 24480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Slot* slot) const { 2460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2490d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { 2500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 2510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(result_register(), slot_operand); 2520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { 2560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 2570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(slot_operand); 258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2610d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Slot* slot) const { 2620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->Move(result_register(), slot); 2630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 2640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2670d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2710d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 2720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 2730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 2740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2770d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 2780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 2790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ PushRoot(index); 2800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 2810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2830d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 2840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (index == Heap::kUndefinedValueRootIndex || 2850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kNullValueRootIndex || 2860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kFalseValueRootIndex) { 2870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(false_label_); 2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (index == Heap::kTrueValueRootIndex) { 2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(true_label_); 2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 2910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 2920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 2980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3010d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 3020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 3030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), lit); 3040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 3080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Push(lit); 3090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 3130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 3140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 3150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(false_label_); 3160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsTrue() || lit->IsJSObject()) { 3170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(true_label_); 3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 3190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 3200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(false_label_); 3210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(true_label_); 3230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 3250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 3260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(false_label_); 3270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(true_label_); 3290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 3320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), lit); 3330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3380d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count, 3390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 3410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 3460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int count, 3470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 3510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3540d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 3550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count > 1) __ Drop(count - 1); 3580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(Operand(rsp, 0), reg); 359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3620d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count, 3630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 3660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 3680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 3690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3720d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 3730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 3740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT_EQ(materialize_true, materialize_false); 3750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 3760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3790d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 3800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 3810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 3820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done; 3830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 3840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), Factory::true_value()); 3850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 3860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 3870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), Factory::false_value()); 3880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 3930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 3940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 3950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done; 3960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 3970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Push(Factory::true_value()); 3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 3990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 4000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Push(Factory::false_value()); 4010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 4020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4050d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 4060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 4070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(materialize_false == false_label_); 4080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(materialize_true == true_label_); 4090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const { 4130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 4170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 4190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), value_root_index); 4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4230d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 4240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ PushRoot(value_root_index); 4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ jmp(true_label_); 4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ jmp(false_label_); 435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 43980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::DoTest(Label* if_true, 44080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 44180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the inlined tests assumed by the stub. 443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); 444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); 448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiCompare(result_register(), Smi::FromInt(0)); 451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(is_smi, if_true); 454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the ToBoolean stub for all other cases. 456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ToBooleanStub stub; 457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ testq(rax, rax); 460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 46180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns nonzero for true. 46280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 46380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 46680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc, 46780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 46880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 46980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 47080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 47180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 47280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 47380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(NegateCondition(cc), if_false); 47480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 47580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 47680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(if_false); 477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (slot->type()) { 483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOCAL: 485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(rbp, SlotOffset(slot)); 486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::CONTEXT: { 487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int context_chain_length = 4883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->ContextChainLength(slot->var()->scope()); 489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadContext(scratch, context_chain_length); 49059151504615d929945dc59db37bf1166937748c6Steve Block return ContextOperand(scratch, slot->index()); 491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOOKUP: 493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(rax, 0); 497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 500d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) { 501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(source, destination); 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(destination, location); 503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 506d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst, 507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register src, 508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2) { 510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!scratch1.is(src) && !scratch2.is(src)); 512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(dst, scratch1); 513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(location, src); 514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (dst->type() == Slot::CONTEXT) { 516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(scratch1, offset, src, scratch2); 518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable, 523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable::Mode mode, 524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FunctionLiteral* function) { 525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(variable != NULL); // Must have been resolved. 5270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = variable->AsSlot(); 528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = variable->AsProperty(); 529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); 537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 55159151504615d929945dc59db37bf1166937748c6Steve Block __ movq(rbx, ContextOperand(rsi, Context::FCONTEXT_INDEX)); 552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmpq(rbx, rsi); 553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(equal, "Unexpected declaration in current context."); 554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 55759151504615d929945dc59db37bf1166937748c6Steve Block __ movq(ContextOperand(rsi, slot->index()), kScratchRegister); 558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the hole value is in old space. 559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 56159151504615d929945dc59db37bf1166937748c6Steve Block __ movq(ContextOperand(rsi, slot->index()), result_register()); 562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 5634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rbx, rsi); 5644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(rbx, offset, result_register(), rcx); 565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rsi); 570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(variable->name()); 571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(mode == Variable::VAR || mode == Variable::CONST); 573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; 574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(attr)); 575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ PushRoot(Heap::kTheHoleValueRootIndex); 581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(function); 583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(0)); // no initial value! 585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL || mode == Variable::CONST) { 593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL) { 5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->key()); 5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rcx); 600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, result_register()); 603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); 604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 6080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 619d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 6203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 6213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rsi); // The context is the first argument. 6223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(pairs); 6233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ Push(Smi::FromInt(is_eval() ? 1 : 0)); 6243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 6263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 65680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 6570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(rdx, Operand(rsp, 0)); // Switch value. 6580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 66080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 66180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfNotBothSmi(rdx, rax, &slow_case); 66280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiCompare(rdx, rax); 66380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &next_test); 66480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 66580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(clause->body_target()->entry_label()); 66680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 6690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareFlags flags = inline_smi_code 6700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_SMI_COMPARE_IN_STUB 6710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_COMPARE_FLAGS; 6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareStub stub(equal, true, flags); 673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testq(rax, rax); 675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(clause->body_target()->entry_label()); 678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(nested_statement.break_target()); 686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(default_clause->body_target()->entry_label()); 688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(clause->body_target()->entry_label()); 695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(nested_statement.break_target()); 699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the object to enumerate over. Both SpiderMonkey and JSC 711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ignore null and undefined in contrast to the specification; see 712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ECMA-262 section 12.6.4. 7130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kNullValueRootIndex); 717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &convert); 722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, &done_convert); 724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 73059151504615d929945dc59db37bf1166937748c6Steve Block // BUG(867): Check cache validity in generated code. This is a fast 73159151504615d929945dc59db37bf1166937748c6Steve Block // case for the JSObject::IsSimpleEnum cache validity checks. If we 73259151504615d929945dc59db37bf1166937748c6Steve Block // cannot guarantee cache validity, call the runtime system to check 73359151504615d929945dc59db37bf1166937748c6Steve Block // cache validity or get the property names in a fixed array. 734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Duplicate the enumerable object on the stack. 737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 7420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel fixed_array; 743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Heap::kMetaMapRootIndex); 745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &fixed_array); 746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register rax. Get the enumeration cache from it. 748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset)); 749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); 750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Setup the four remaining stack slots. 753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Map. 754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rdx); // Enumeration cache. 755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); 756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Enumeration cache length (as smi). 757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Initial index. 758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register rax. Iterate through that. 761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Map (0) - force slow check. 763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Fixed array length (as smi). 766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Initial index. 767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. 771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. 772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, loop_statement.break_target()); 773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register rbx. 775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, Operand(rsp, 2 * kPointerSize)); 776f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); 777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rbx, 778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize)); 781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the expected map from the stack or a zero map in the 783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register rdx. 784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 3 * kPointerSize)); 785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If not, we have to filter the key. 7880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel update_each; 789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, Operand(rsp, 4 * kPointerSize)); 790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); 791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &update_each); 792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the entry to a string or null if it isn't a property 794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // anymore. If the property has been removed while iterating, we 795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rcx); // Enumerable. 797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rbx); // Current entry. 798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 799756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ SmiCompare(rax, Smi::FromInt(0)); 800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, loop_statement.continue_target()); 801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, rax); 802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register rbx. 805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(result_register(), rbx); 807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitAssignment(stmt->each()); 809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label stack_limit_hit, stack_check_done; 812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ StackLimitCheck(&stack_limit_hit); 815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_check_done); 816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for going to the next element by incrementing the 818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // index (smi) stored on top of the stack. 819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.continue_target()); 820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); 821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Slow case for the stack limit check. 824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StackCheckStub stack_check_stub; 825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_limit_hit); 826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stack_check_stub); 827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&stack_check_done); 828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.break_target()); 831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ addq(rsp, Immediate(5 * kPointerSize)); 832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 8373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) { 840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // space for nested functions that don't need literals cloning. 842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && info->num_literals() == 0) { 843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastNewClosureStub stub; 844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(info); 845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rsi); 848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(info); 849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kNewClosure, 2); 850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 8510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 8523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 855d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 8563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 8570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->var()); 858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 86159151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( 86259151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 86359151504615d929945dc59db37bf1166937748c6Steve Block TypeofState typeof_state, 86459151504615d929945dc59db37bf1166937748c6Steve Block Label* slow) { 86559151504615d929945dc59db37bf1166937748c6Steve Block Register context = rsi; 86659151504615d929945dc59db37bf1166937748c6Steve Block Register temp = rdx; 86759151504615d929945dc59db37bf1166937748c6Steve Block 86859151504615d929945dc59db37bf1166937748c6Steve Block Scope* s = scope(); 86959151504615d929945dc59db37bf1166937748c6Steve Block while (s != NULL) { 87059151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 87159151504615d929945dc59db37bf1166937748c6Steve Block if (s->calls_eval()) { 87259151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 87359151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 87459151504615d929945dc59db37bf1166937748c6Steve Block Immediate(0)); 87559151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 87659151504615d929945dc59db37bf1166937748c6Steve Block } 87759151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 87859151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX)); 87959151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset)); 88059151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering rsi. 88159151504615d929945dc59db37bf1166937748c6Steve Block context = temp; 88259151504615d929945dc59db37bf1166937748c6Steve Block } 88359151504615d929945dc59db37bf1166937748c6Steve Block // If no outer scope calls eval, we do not need to check more 88459151504615d929945dc59db37bf1166937748c6Steve Block // context extensions. If we have reached an eval scope, we check 88559151504615d929945dc59db37bf1166937748c6Steve Block // all extensions from this point. 88659151504615d929945dc59db37bf1166937748c6Steve Block if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; 88759151504615d929945dc59db37bf1166937748c6Steve Block s = s->outer_scope(); 88859151504615d929945dc59db37bf1166937748c6Steve Block } 88959151504615d929945dc59db37bf1166937748c6Steve Block 89059151504615d929945dc59db37bf1166937748c6Steve Block if (s != NULL && s->is_eval_scope()) { 89159151504615d929945dc59db37bf1166937748c6Steve Block // Loop up the context chain. There is no frame effect so it is 89259151504615d929945dc59db37bf1166937748c6Steve Block // safe to use raw labels here. 8930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel next, fast; 89459151504615d929945dc59db37bf1166937748c6Steve Block if (!context.is(temp)) { 89559151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, context); 89659151504615d929945dc59db37bf1166937748c6Steve Block } 89759151504615d929945dc59db37bf1166937748c6Steve Block // Load map for comparison into register, outside loop. 89859151504615d929945dc59db37bf1166937748c6Steve Block __ LoadRoot(kScratchRegister, Heap::kGlobalContextMapRootIndex); 89959151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&next); 90059151504615d929945dc59db37bf1166937748c6Steve Block // Terminate at global context. 90159151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset)); 90259151504615d929945dc59db37bf1166937748c6Steve Block __ j(equal, &fast); 90359151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 90459151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); 90559151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 90659151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 90759151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, ContextOperand(temp, Context::CLOSURE_INDEX)); 90859151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset)); 90959151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(&next); 91059151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&fast); 91159151504615d929945dc59db37bf1166937748c6Steve Block } 91259151504615d929945dc59db37bf1166937748c6Steve Block 91359151504615d929945dc59db37bf1166937748c6Steve Block // All extension objects were empty and it is safe to use a global 91459151504615d929945dc59db37bf1166937748c6Steve Block // load IC call. 91559151504615d929945dc59db37bf1166937748c6Steve Block __ movq(rax, CodeGenerator::GlobalObject()); 91659151504615d929945dc59db37bf1166937748c6Steve Block __ Move(rcx, slot->var()->name()); 91759151504615d929945dc59db37bf1166937748c6Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 91859151504615d929945dc59db37bf1166937748c6Steve Block RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 91959151504615d929945dc59db37bf1166937748c6Steve Block ? RelocInfo::CODE_TARGET 92059151504615d929945dc59db37bf1166937748c6Steve Block : RelocInfo::CODE_TARGET_CONTEXT; 9210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 92259151504615d929945dc59db37bf1166937748c6Steve Block} 92359151504615d929945dc59db37bf1166937748c6Steve Block 92459151504615d929945dc59db37bf1166937748c6Steve Block 92559151504615d929945dc59db37bf1166937748c6Steve BlockMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( 92659151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 92759151504615d929945dc59db37bf1166937748c6Steve Block Label* slow) { 92859151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(slot->type() == Slot::CONTEXT); 92959151504615d929945dc59db37bf1166937748c6Steve Block Register context = rsi; 93059151504615d929945dc59db37bf1166937748c6Steve Block Register temp = rbx; 93159151504615d929945dc59db37bf1166937748c6Steve Block 93259151504615d929945dc59db37bf1166937748c6Steve Block for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { 93359151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 93459151504615d929945dc59db37bf1166937748c6Steve Block if (s->calls_eval()) { 93559151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 93659151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 93759151504615d929945dc59db37bf1166937748c6Steve Block Immediate(0)); 93859151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 93959151504615d929945dc59db37bf1166937748c6Steve Block } 94059151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX)); 94159151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset)); 94259151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering rsi. 94359151504615d929945dc59db37bf1166937748c6Steve Block context = temp; 94459151504615d929945dc59db37bf1166937748c6Steve Block } 94559151504615d929945dc59db37bf1166937748c6Steve Block } 94659151504615d929945dc59db37bf1166937748c6Steve Block // Check that last extension is NULL. 94759151504615d929945dc59db37bf1166937748c6Steve Block __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); 94859151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 94959151504615d929945dc59db37bf1166937748c6Steve Block __ movq(temp, ContextOperand(context, Context::FCONTEXT_INDEX)); 95059151504615d929945dc59db37bf1166937748c6Steve Block return ContextOperand(temp, slot->index()); 95159151504615d929945dc59db37bf1166937748c6Steve Block} 95259151504615d929945dc59db37bf1166937748c6Steve Block 95359151504615d929945dc59db37bf1166937748c6Steve Block 95459151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( 95559151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 95659151504615d929945dc59db37bf1166937748c6Steve Block TypeofState typeof_state, 95759151504615d929945dc59db37bf1166937748c6Steve Block Label* slow, 95859151504615d929945dc59db37bf1166937748c6Steve Block Label* done) { 95959151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast-case code for variables that might be shadowed by 96059151504615d929945dc59db37bf1166937748c6Steve Block // eval-introduced variables. Eval is used a lot without 96159151504615d929945dc59db37bf1166937748c6Steve Block // introducing variables. In those cases, we do not want to 96259151504615d929945dc59db37bf1166937748c6Steve Block // perform a runtime call for all variables in the scope 96359151504615d929945dc59db37bf1166937748c6Steve Block // containing the eval. 96459151504615d929945dc59db37bf1166937748c6Steve Block if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 96559151504615d929945dc59db37bf1166937748c6Steve Block EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); 96659151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 96759151504615d929945dc59db37bf1166937748c6Steve Block } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { 9680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); 96959151504615d929945dc59db37bf1166937748c6Steve Block Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); 97059151504615d929945dc59db37bf1166937748c6Steve Block if (potential_slot != NULL) { 97159151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast case for locals that rewrite to slots. 97259151504615d929945dc59db37bf1166937748c6Steve Block __ movq(rax, 97359151504615d929945dc59db37bf1166937748c6Steve Block ContextSlotOperandCheckExtensions(potential_slot, slow)); 97459151504615d929945dc59db37bf1166937748c6Steve Block if (potential_slot->var()->mode() == Variable::CONST) { 97559151504615d929945dc59db37bf1166937748c6Steve Block __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 97659151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, done); 97759151504615d929945dc59db37bf1166937748c6Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 97859151504615d929945dc59db37bf1166937748c6Steve Block } 97959151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 98059151504615d929945dc59db37bf1166937748c6Steve Block } else if (rewrite != NULL) { 98159151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast case for calls of an argument function. 98259151504615d929945dc59db37bf1166937748c6Steve Block Property* property = rewrite->AsProperty(); 98359151504615d929945dc59db37bf1166937748c6Steve Block if (property != NULL) { 98459151504615d929945dc59db37bf1166937748c6Steve Block VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 98559151504615d929945dc59db37bf1166937748c6Steve Block Literal* key_literal = property->key()->AsLiteral(); 98659151504615d929945dc59db37bf1166937748c6Steve Block if (obj_proxy != NULL && 98759151504615d929945dc59db37bf1166937748c6Steve Block key_literal != NULL && 98859151504615d929945dc59db37bf1166937748c6Steve Block obj_proxy->IsArguments() && 98959151504615d929945dc59db37bf1166937748c6Steve Block key_literal->handle()->IsSmi()) { 99059151504615d929945dc59db37bf1166937748c6Steve Block // Load arguments object if there are no eval-introduced 99159151504615d929945dc59db37bf1166937748c6Steve Block // variables. Then load the argument from the arguments 99259151504615d929945dc59db37bf1166937748c6Steve Block // object using keyed load. 99359151504615d929945dc59db37bf1166937748c6Steve Block __ movq(rdx, 9940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), 99559151504615d929945dc59db37bf1166937748c6Steve Block slow)); 99659151504615d929945dc59db37bf1166937748c6Steve Block __ Move(rax, key_literal->handle()); 99759151504615d929945dc59db37bf1166937748c6Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 9980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 99959151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 100059151504615d929945dc59db37bf1166937748c6Steve Block } 100159151504615d929945dc59db37bf1166937748c6Steve Block } 100259151504615d929945dc59db37bf1166937748c6Steve Block } 100359151504615d929945dc59db37bf1166937748c6Steve Block } 100459151504615d929945dc59db37bf1166937748c6Steve Block} 100559151504615d929945dc59db37bf1166937748c6Steve Block 100659151504615d929945dc59db37bf1166937748c6Steve Block 10070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitVariableLoad(Variable* var) { 1008d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Four cases: non-this global variables, lookup slots, all other 1009d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // types of slots, and parameters that rewrite to explicit property 1010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // accesses on the arguments object. 10110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = var->AsSlot(); 1012d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Property* property = var->AsProperty(); 1013d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1014d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (var->is_global() && !var->is_this()) { 10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "Global variable"); 10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use inline caching. Variable name is passed in rcx and the global 10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // object on the stack. 1018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, var->name()); 10197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ movq(rax, CodeGenerator::GlobalObject()); 10203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 10210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 10220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1024d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 102559151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 102659151504615d929945dc59db37bf1166937748c6Steve Block 102759151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 102859151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 102959151504615d929945dc59db37bf1166937748c6Steve Block EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 103059151504615d929945dc59db37bf1166937748c6Steve Block 103159151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 1032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Lookup slot"); 1033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rsi); // Context. 1034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ Push(var->name()); 1035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 103659151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 103759151504615d929945dc59db37bf1166937748c6Steve Block 10380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1039d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL) { 1041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ? "Context slot" 1043d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : "Stack slot"); 1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (var->mode() == Variable::CONST) { 1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Constants may be the hole value if they have not been initialized. 1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Unhole them. 10470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done; 1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke MemOperand slot_operand = EmitSlotSearch(slot, rax); 1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, slot_operand); 1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 10540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 10560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(slot); 1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1058d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1059d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1060d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Rewritten parameter"); 1061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(property); 1062d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Rewritten parameter accesses are of the form "slot[literal]". 1063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the object is in a slot. 1065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 1066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NOT_NULL(object_var); 10670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* object_slot = object_var->AsSlot(); 1068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_slot); 1069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the object. 1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand object_loc = EmitSlotSearch(object_slot, rax); 10727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ movq(rdx, object_loc); 1073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the key is a smi. 1075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key_literal = property->key()->AsLiteral(); 1076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(key_literal); 1077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(key_literal->handle()->IsSmi()); 1078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the key. 10807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(rax, key_literal->handle()); 1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a keyed property load. 1083d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 10840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 10850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1090d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 1092bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label materialized; 10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rdi = JS function. 1095bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rcx = literals array. 1096bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rbx = regexp literal. 1097bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rax = regexp literal clone. 10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1099bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 110180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1102bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rbx, FieldOperand(rcx, literal_offset)); 1103bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 1104bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &materialized); 1105bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create regexp literal using runtime function 11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Result will be in rax. 1108bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(rcx); 11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->pattern()); 11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->flags()); 11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1113bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rbx, rax); 1114bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1115bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&materialized); 1116bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1117bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label allocated, runtime_allocate; 1118bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 1119bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&allocated); 1120bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1121bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&runtime_allocate); 1122bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(rbx); 1123bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Push(Smi::FromInt(size)); 1124bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1125bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(rbx); 1126bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1127bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&allocated); 1128bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Copy the content into the newly allocated memory. 1129bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // (Unroll copy loop once for better throughput). 1130bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 1131bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rdx, FieldOperand(rbx, i)); 1132bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); 1133bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, i), rdx); 1134bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, i + kPointerSize), rcx); 1135bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1136bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if ((size % (2 * kPointerSize)) != 0) { 1137bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); 1138bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, size - kPointerSize), rdx); 1139bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 11400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 1146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(expr->literal_index())); 1149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(expr->constant_properties()); 11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(Smi::FromInt(expr->fast_elements() ? 1 : 0)); 1151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->depth() > 1) { 11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 11533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4); 1155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1158e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in rax. 1159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Save result on the stack 1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::CONSTANT: 1173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 1174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 11790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(value); 1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, key->handle()); 11814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 11830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 11890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 11900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kSetProperty, 3); 1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::SETTER: 1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::GETTER: 1195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 11960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(property->kind() == ObjectLiteral::Property::SETTER ? 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(1) : 1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(0)); 12000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 1201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDefineAccessor, 4); 1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 12070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 12090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 1219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 1223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(expr->constant_elements()); 1224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) { 1225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub stub( 1226756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); 1227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 1228756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ IncrementCounter(&Counters::cow_arrays_created_stub, 1); 1229756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (expr->depth() > 1) { 1230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 1232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub stub( 1235756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub::CLONE_ELEMENTS, length); 1236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 12443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 12453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 12463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 12473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 12483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 12493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 12533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 12543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 12553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 12573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Store the subexpression value in the array's elements. 12593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 12603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 12613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(FieldOperand(rbx, offset), result_register()); 12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Update the write barrier for the array store. 1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(rbx, offset, result_register(), rcx); 12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 12690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 12710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 12723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1276402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1277402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1285402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 1286402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1287402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1288402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 128980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 129080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (property != NULL) { 129180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen assign_type = (property->key()->IsPropertyName()) 129280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? NAMED_PROPERTY 129380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : KEYED_PROPERTY; 1294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1295402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1296402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1298402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1299402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1300402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1301402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 13040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(property->obj()); 1305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 13070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->is_compound()) { 13120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 13130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(property->key()); 1314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 0)); 1315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 1316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 13170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 13180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->key()); 1319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1320402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1323402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 13240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 13250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 13260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 13270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->target()->AsVariableProxy()->var()); 13280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 13290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 13300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 13310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 13320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 13330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 13340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 13350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 133880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 133980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ConstantOperand constant = ShouldInlineSmiCase(op) 134080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? GetConstantOperand(op, expr->target(), expr->value()) 134180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : kNoConstants; 134280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(constant == kRightConstant || constant == kNoConstants); 134380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (constant == kNoConstants) { 134480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(rax); // Left operand goes on the stack. 13450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 134680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 134880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 134980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? OVERWRITE_RIGHT 135080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : NO_OVERWRITE; 135180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position() + 1); 13520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 135380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 135480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EmitInlineSmiBinaryOp(expr, 135580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 135680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mode, 135780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 135880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->value(), 135980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen constant); 136080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 13610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitBinaryOp(op, mode); 136280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 136380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 13640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1373402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 13740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen expr->op()); 1375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1384402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1386d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, key->handle()); 1390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 13910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 13980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 140280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, 140380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 140480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 140580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 140680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right, 140780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ConstantOperand constant) { 140880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(constant == kNoConstants); // Only handled case. 140980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 141080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Do combined smi check of the operands. Left operand is on the 141180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // stack (popped into rdx). Right operand is in rax but moved into 141280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx to make the shifts easier. 141380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label done, stub_call, smi_case; 141480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ pop(rdx); 141580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rcx, rax); 1416f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Condition smi = masm()->CheckBothSmi(rdx, rax); 141780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(smi, &smi_case); 141880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 141980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&stub_call); 142080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); 142180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (stub.ArgsInRegistersSupported()) { 142280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen stub.GenerateCall(masm_, rdx, rcx); 142380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(rdx); 142580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(rcx); 142680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallStub(&stub); 142780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 142880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&done); 142980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 143080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&smi_case); 143180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 143280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SAR: 143380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftArithmeticRight(rax, rdx, rcx); 143480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 143580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHL: 143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftLeft(rax, rdx, rcx); 143780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 143880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHR: 143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call); 144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 144180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::ADD: 144280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiAdd(rax, rdx, rcx, &stub_call); 144380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 144480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SUB: 144580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiSub(rax, rdx, rcx, &stub_call); 144680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 144780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::MUL: 144880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiMul(rax, rdx, rcx, &stub_call); 144980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 145080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_OR: 145180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiOr(rax, rdx, rcx); 145280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 145380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_AND: 145480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiAnd(rax, rdx, rcx); 145580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 145680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_XOR: 145780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiXor(rax, rdx, rcx); 145880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 145980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen default: 146080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UNREACHABLE(); 146180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 146280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 146380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 146480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 14650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 146680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 146780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 146880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1469d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 147080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode) { 147180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS); 147280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (stub.ArgsInRegistersSupported()) { 147380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ pop(rdx); 147480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen stub.GenerateCall(masm_, rdx, rax); 147580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 147680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(result_register()); 147780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallStub(&stub); 147880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 14790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 1492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 15050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 15060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(var, Token::ASSIGN); 1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Preserve value. 15110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 1512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 1513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rax); // Restore value. 1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rcx, prop->key()->AsLiteral()->handle()); 1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 15160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Preserve value. 15210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 15220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 15238defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ movq(rcx, rax); 15248defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ pop(rdx); 15258defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ pop(rax); 1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 15270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 15350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::Value op) { 1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand sides that rewrite to explicit property accesses do not reach 1537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // here. 15383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 15390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(var->is_global() || var->AsSlot() != NULL); 1540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in rax, variable name in 1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rcx, and the global object on the stack. 15463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Move(rcx, var->name()); 15474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, CodeGenerator::GlobalObject()); 15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 15490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment for non-const variables and for initialization 1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // of const variables. Const assignments are simply skipped. 1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 15550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = var->AsSlot(); 1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Slot::LOCAL: 1559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rbp, SlotOffset(slot))); 1562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment. 1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(Operand(rbp, SlotOffset(slot)), rax); 1567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, rcx); 1571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, target); 1574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment and issue the write barrier. 1578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(target, rax); 1579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The value of the assignment is in rax. RecordWrite clobbers its 1580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // register arguments. 1581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 1582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(rcx, offset, rdx, rbx); 1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call the runtime for the assignment. The runtime will ignore 1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // const reinitialization. 1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Value. 1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rsi); // Context. 1592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 1593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime will ignore const redeclaration. 1595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 16040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1608d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 16133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, kPointerSize)); // Receiver is now under value. 1620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, prop->key()->AsLiteral()->handle()); 16274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (expr->ends_initialization_block()) { 16284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 16294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 16304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 16314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 16330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 16410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, rax); 16424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 16430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1648d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, 2 * kPointerSize)); 1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rcx); 1663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->ends_initialization_block()) { 1664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. 1665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 1667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 16710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rdx); 1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 16820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1686d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 16910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->obj()); 1692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 16940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->obj()); 16950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->key()); 16967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(rdx); 1697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 1698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 16990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 1704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Object> name, 1705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 17083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 17093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 17100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 17113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Move(rcx, name); 1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 17143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SetSourcePosition(expr->position()); 17153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 1716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 17173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke in_loop); 17190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 1720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 17220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 17269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 17279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Expression* key, 17289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen RelocInfo::Mode mode) { 17299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Code common for calls using the IC. 17309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ZoneList<Expression*>* args = expr->arguments(); 17319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int arg_count = args->length(); 17329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0; i < arg_count; i++) { 17330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 17349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 17350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(key); 17369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ movq(rcx, rax); 17379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source position for debugger. 17389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen SetSourcePosition(expr->position()); 17399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call the IC initialization code. 17409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 17419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, 17429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen in_loop); 17430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 17449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Restore context register. 17459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 17460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 17479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 17489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 17499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1750d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 1751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 1752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 17550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 17623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 17633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 17643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Discard the function left on TOS. 17650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, rax); 1766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1769d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 1770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 1771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 1772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 1773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 1775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 1776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // resolve the function we need to call and the receiver of the 1777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. The we call the resolved function using the given 1778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 17790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(fun); 1780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. 1781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the arguments. 1783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 1784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 1785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 17860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 1787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the function - found below the arguments. 1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); 1791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the first argument or undefined if it doesn't exist. 1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (arg_count > 0) { 1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(rsp, arg_count * kPointerSize)); 1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 1797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the receiver of the enclosing function and do runtime call. 1800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); 1801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 1802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime call returns a pair of values in rax (function) and 1804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rdx (receiver). Touch up the stack with the right values. 1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 1806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 1807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 1809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetSourcePosition(expr->position()); 1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 18150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, rax); 1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a global variable. 1818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object as receiver for the call IC lookup. 1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 18210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (var != NULL && var->AsSlot() != NULL && 18220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot()->type() == Slot::LOOKUP) { 182359151504615d929945dc59db37bf1166937748c6Steve Block // Call to a lookup slot (dynamically introduced variable). 182459151504615d929945dc59db37bf1166937748c6Steve Block Label slow, done; 182559151504615d929945dc59db37bf1166937748c6Steve Block 182659151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 182759151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 18280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitDynamicLoadFromSlotFastCase(var->AsSlot(), 182959151504615d929945dc59db37bf1166937748c6Steve Block NOT_INSIDE_TYPEOF, 183059151504615d929945dc59db37bf1166937748c6Steve Block &slow, 183159151504615d929945dc59db37bf1166937748c6Steve Block &done); 183259151504615d929945dc59db37bf1166937748c6Steve Block 183359151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 183459151504615d929945dc59db37bf1166937748c6Steve Block // Call the runtime to find the function to call (returned in rax) 183559151504615d929945dc59db37bf1166937748c6Steve Block // and the object holding it (returned in rdx). 1836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 1837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 1838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Function. 1840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rdx); // Receiver. 184159151504615d929945dc59db37bf1166937748c6Steve Block 184259151504615d929945dc59db37bf1166937748c6Steve Block // If fast case code has been generated, emit code to push the 184359151504615d929945dc59db37bf1166937748c6Steve Block // function and receiver and have the slow path jump around this 184459151504615d929945dc59db37bf1166937748c6Steve Block // code. 184559151504615d929945dc59db37bf1166937748c6Steve Block if (done.is_linked()) { 18460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel call; 184759151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(&call); 184859151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 184959151504615d929945dc59db37bf1166937748c6Steve Block // Push function. 185059151504615d929945dc59db37bf1166937748c6Steve Block __ push(rax); 185159151504615d929945dc59db37bf1166937748c6Steve Block // Push global receiver. 185259151504615d929945dc59db37bf1166937748c6Steve Block __ movq(rbx, CodeGenerator::GlobalObject()); 185359151504615d929945dc59db37bf1166937748c6Steve Block __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 185459151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&call); 185559151504615d929945dc59db37bf1166937748c6Steve Block } 185659151504615d929945dc59db37bf1166937748c6Steve Block 1857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitCallWithStub(expr); 185859151504615d929945dc59db37bf1166937748c6Steve Block 1859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 1860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 1861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 1862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 1863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 1864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 18650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 1866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 18689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call to a keyed property. 18699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // For a synthetic property use keyed load IC followed by function call, 18709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // for a regular property use KeyedCallIC. 18710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 1872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (prop->is_synthetic()) { 18730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 18749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ movq(rdx, Operand(rsp, 0)); 18759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source code position for IC call. 18769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen SetSourcePosition(prop->position()); 18779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 18780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 18799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Pop receiver. 18809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ pop(rbx); 18819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Push result (function). 18829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ push(rax); 18839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Push receiver object on stack. 1884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rcx, CodeGenerator::GlobalObject()); 1885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 18869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen EmitCallWithStub(expr); 1887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 18889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 1889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 18913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 1893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 1894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // also use the fast code generator. 1895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 1897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 1899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 1900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 19010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(fun); 1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rbx, CodeGenerator::GlobalObject()); 1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 191780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 191980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 19200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->expression()); 1921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 19260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 19273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 193380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into rdi and rax. 1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(rax, arg_count); 193580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rdi, Operand(rsp, arg_count * kPointerSize)); 1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 19403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 19413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 19423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 195180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 19530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_true); 1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 197080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 19720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1974f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); 1975f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Split(non_negative_smi, if_true, if_false, fall_through); 1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 198980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 19900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 19910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kNullValueRootIndex); 1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_false); 2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); 2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, if_false); 2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); 200580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(below_equal, if_true, if_false, fall_through); 2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 20123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(args->length() == 1); 20133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 20153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 20173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 20183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 201980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 20223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ JumpIfSmi(rax, if_false); 20243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 202580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(above_equal, if_true, if_false, fall_through); 20263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 20283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 20293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 2031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 203980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 204780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2053756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2054756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ZoneList<Expression*>* args) { 2055756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ASSERT(args->length() == 1); 2056756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 20570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2058756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2059756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label materialize_true, materialize_false; 2060756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_true = NULL; 2061756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_false = NULL; 206280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2065756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2066756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only 2067756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // used in a few functions in runtime.js which should not normally be hit by 2068756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // this compiler. 2069756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ jmp(if_false); 20700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2071756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2072756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2073756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 208280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 208880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 210280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 21030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 21040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 210880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 212280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 21230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 21240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 212880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 214180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 21420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 21430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), 2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &check_frame_marker); 2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), 2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Smi::FromInt(StackFrame::CONSTRUCT)); 215980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 21690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 21700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 217580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 21760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 21770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rbx); 2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rax, rbx); 218180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 219080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ArgumentsAccessStub expects the key in rdx and the formal 219180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // parameter count in rax. 21920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 21970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel exit; 2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset), 2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &exit); 2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (FLAG_debug_code) __ AbortIfNotSmi(rax); 22200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &null); 2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); // Map is now in rax. 2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, &null); 2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // As long as JS_FUNCTION_TYPE is the last instance type and it is 2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // LAST_JS_OBJECT_TYPE. 2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpInstanceType(rax, JS_FUNCTION_TYPE); 2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &function); 2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the constructor in the map is a function. 2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, Map::kConstructorOffset)); 2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &non_function_constructor); 2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rax now contains the constructor function. Grab the 2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); 2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); 2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rax, Factory::function_class_symbol()); 2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rax, Factory::Object_symbol()); 2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kNullValueRootIndex); 2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING 2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 22890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 22900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif 2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 22960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber); 2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 23103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Allocate a heap number. 23113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, rax); 2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Return a random uint32 number in rax. 2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. 2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(0); 2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction(ExternalReference::random_uint32_function(), 0); 2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in rax to 0.(32 random bits) in a double 2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm1, rcx); 2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm0, rax); 2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cvtss2sd(xmm1, xmm1); 2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ xorpd(xmm0, xmm1); 2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ subsd(xmm0, xmm1); 2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0); 2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, rbx); 23330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 23410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 23420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 23430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 23450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 23530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 23540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 23550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 23560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(3)); 2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 23580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); // Load the object. 2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &done); 2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); 2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, JSValue::kValueOffset)); 2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 23760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 23830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 23840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_pow, 2); 23860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Load the object. 23940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); // Load the value. 239580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ pop(rbx); // rax = value. rbx = object. 2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rbx, &done); 2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); 2403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax); 2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 2410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx); 2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 24130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 24210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 24250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(rax, rbx); 24367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 24377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 24407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 24430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rbx); 24447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 24457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 24487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 24497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 24510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 24527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 24547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 24557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = rcx; 24567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rdx; 24577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 24597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 24617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 24627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 24647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 24657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch, 24667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 24677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 24707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 24717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 24757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 24767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 24777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 24787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 24817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move the undefined value into the result register, which will 24827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 24847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 24877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 24900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 24957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 24967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 24980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 24997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 25017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 25027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = rcx; 25037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = rdx; 25047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rax; 25057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 25077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 25097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 25107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 25117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 25127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 25137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 25147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 25157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 25167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 25177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 25187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 25197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 25207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 25217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 25247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 25257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 25267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kEmptyStringRootIndex); 25277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 25307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 25317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 25327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(result, Smi::FromInt(0)); 25337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 25367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 25377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 25390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 25470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 25510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 25590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 25630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke TranscendentalCacheStub stub(TranscendentalCache::SIN); 2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 25710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 25730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke TranscendentalCacheStub stub(TranscendentalCache::COS); 2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 25810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 25830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime function. 2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 25900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sqrt, 1); 25920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length() - 2; // For receiver and function. 26000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Receiver. 2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 26020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i + 1)); 2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 26040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(arg_count + 1)); // Function. 2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // InvokeFunction requires function in rdi. Move it in there. 2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!result_register().is(rdi)) __ movq(rdi, result_register()); 2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeFunction(rdi, count, CALL_FUNCTION); 2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 26110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 26170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 26180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 26190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kRegExpConstructResult, 3); 26210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 26270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 26280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 26290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kSwapElements, 3); 26310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Top::global_context()->jsfunction_result_caches()); 2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 26460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = rax; 2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = rbx; 2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register tmp = rcx; 265559151504615d929945dc59db37bf1166937748c6Steve Block __ movq(cache, ContextOperand(rsi, Context::GLOBAL_INDEX)); 2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, GlobalObject::kGlobalContextOffset)); 2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 265959151504615d929945dc59db37bf1166937748c6Steve Block ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done, not_found; 2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SmiIndex index = 2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2); 2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(key, FieldOperand(cache, 2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize)); 2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, ¬_found); 2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(cache, 2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize + kPointerSize)); 2678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(cache); 2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(key); 2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 26870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2691bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 2692bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT_EQ(2, args->length()); 2693bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2694bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register right = rax; 2695bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register left = rbx; 2696bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp = rcx; 2697bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 26980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 26990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2700bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(left); 2701bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done, fail, ok; 2703bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(left, right); 2704bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(equal, &ok); 2705bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Fail if either is a non-HeapObject. 2706bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Condition either_smi = masm()->CheckEitherSmi(left, right, tmp); 2707bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(either_smi, &fail); 2708bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(zero, &fail); 2709bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset)); 2710bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset), 2711bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Immediate(JS_REGEXP_TYPE)); 2712bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &fail); 2713bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset)); 2714bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &fail); 2715bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset)); 2716bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset)); 2717bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(equal, &ok); 2718bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&fail); 2719bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Move(rax, Factory::false_value()); 2720bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&done); 2721bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&ok); 2722bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Move(rax, Factory::true_value()); 2723bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&done); 2724bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2726bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2727bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2728bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 272980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { 273080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(args->length() == 1); 273180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 27320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 273380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 273480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 273580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 273680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 273780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 27380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 27390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 274080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 274180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testl(FieldOperand(rax, String::kHashFieldOffset), 274280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(String::kContainsCachedArrayIndexMask)); 274380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, if_true); 274480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(if_false); 274580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 27460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 274780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 274880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 274980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 275080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 275180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(args->length() == 1); 275280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 27530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 275480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 275580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); 275680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(String::kHashShift >= kSmiTagSize); 275780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(rax, rax); 275880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 27590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 276080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 276180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 276280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2763d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 27723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 27733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 2776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rax, CodeGenerator::GlobalObject()); 2777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 2778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 27793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 27803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 27813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 27823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 27830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 2784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2787402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Call the JS runtime function using a call IC. 2788402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Move(rcx, expr->name()); 2789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2790402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 27910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 2792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 2796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 27970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2801d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->expression()->AsProperty(); 2806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop == NULL && var == NULL) { 2808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-property, non-variable reference is true. 2809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression may have side effects. 2810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 28110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(true); 2812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var != NULL && 2813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke !var->is_global() && 28140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot() != NULL && 28150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot()->type() != Slot::LOOKUP) { 2816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-global, non-dynamic variables is false. 2817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression does not have side effects. 28180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(false); 2819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Property or variable reference. Call the delete builtin with 2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object and property name as arguments. 2822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 28230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 28240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->key()); 2825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->is_global()) { 2826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(CodeGenerator::GlobalObject()); 2827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 2828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-global variable. Call the runtime to look up the context 2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // where the variable was introduced. 2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLookupContext, 2); 2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 28380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 2844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 28460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Heap::kUndefinedValueRootIndex); 2847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 2851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 285580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 2856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Notice that the labels are swapped. 28570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 28580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_false, &if_true, &fall_through); 285980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VisitForControl(expr->expression(), if_true, if_false, fall_through); 28600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_false, if_true); // Labels swapped. 2861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 2865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 28660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { StackValueContext context(this); 28670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 28680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 28700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 2875d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 28760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 28770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel no_conversion; 28784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 2879d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &no_conversion); 2880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(result_register()); 2881d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 2882d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 28830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result_register()); 2884d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 2885d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 28874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 28884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 288980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 2890ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke UnaryOverwriteMode overwrite = 2891ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 28920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenericUnaryOpStub stub(Token::SUB, overwrite, NO_UNARY_FLAGS); 28934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 28944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register rax. 28950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 28964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 28970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 28984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 28994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 29004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 29014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 29024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 290380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The generic unary operation stub expects the argument to be 290480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // in the accumulator register rax. 29050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 290680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label done; 29070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_case = ShouldInlineSmiCase(expr->op()); 29080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_case) { 290980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label call_stub; 291080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfNotSmi(rax, &call_stub); 291180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiNot(rax, rax); 291280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&done); 291380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&call_stub); 291480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 291580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool overwrite = expr->expression()->ResultOverwriteAllowed(); 291680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UnaryOverwriteMode mode = 291780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 29180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen UnaryOpFlags flags = inline_smi_case 29190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_UNARY_SMI_CODE_IN_STUB 29200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_UNARY_FLAGS; 29210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags); 29224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 29234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 29240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 29254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 29264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 29274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 29303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 29313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 29323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 29333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2934d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Comment cmnt(masm_, "[ CountOperation"); 293680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 2937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand-sides are rewritten to have a 'throw 2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' as the left-hand side. 2940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 2946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 2947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 2949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 2950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 2951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 2952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 2953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 2954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 2955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 2958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 2959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 29600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 29610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 2962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 29640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 2965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Smi::FromInt(0)); 2966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 29680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 29697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(rax); // Copy of receiver, needed for later store. 2970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 2971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 29720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 29730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 29747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 29757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(rax); // Copy of key, needed for later store. 2976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 2977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2980d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 29810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel no_conversion; 2982d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Condition is_smi; 2983d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke is_smi = masm_->CheckSmi(rax); 2984d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &no_conversion); 2985d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rax); 2986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 2987d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 2988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 2990e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 29910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 29920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 29930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 29940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 29950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 29960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 29970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(rax); 29980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 29990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 30000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(Operand(rsp, kPointerSize), rax); 30010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 30020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 30030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movq(Operand(rsp, 2 * kPointerSize), rax); 30040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3009d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 3010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 301180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(expr->op())) { 3012d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 3013d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 3014d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 3015d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 3016d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3017d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(overflow, &stub_call); 3018d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 3019d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 3020d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke is_smi = masm_->CheckSmi(rax); 3021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &done); 3022d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 3023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 3024d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 3025d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 3026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 3027d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 3028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 3031e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(expr->binary_op(), 3032e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 3033e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_GENERIC_BINARY_FLAGS); 30344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke stub.GenerateCall(masm_, rax, Smi::FromInt(1)); 3035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 3036e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3037e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in rax. 3038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 3039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 3040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 3041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 30420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 30430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 30440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 30450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 3047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 30480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 30490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3050e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3051e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 3053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 30540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 3055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 3058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, prop->key()->AsLiteral()->handle()); 30594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 3060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 30610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 3062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 30630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 30640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 30670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3069e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 3072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rcx); 3073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 3074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 30750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 3076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 30770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 30780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 30810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3085e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3086e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3087e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 30890d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 309080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VariableProxy* proxy = expr->AsVariableProxy(); 30910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsEffect()); 30920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsTest()); 30930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 309480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 309580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Comment cmnt(masm_, "Global variable"); 309680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Move(rcx, proxy->name()); 309780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rax, CodeGenerator::GlobalObject()); 309880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 309980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Use a regular load, not a contextual load, to avoid a reference 310080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // error. 31010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 31020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 310380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (proxy != NULL && 31040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen proxy->var()->AsSlot() != NULL && 31050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 310659151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 310759151504615d929945dc59db37bf1166937748c6Steve Block 310859151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 310959151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 31100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = proxy->var()->AsSlot(); 311159151504615d929945dc59db37bf1166937748c6Steve Block EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 311259151504615d929945dc59db37bf1166937748c6Steve Block 311359151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 311480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(rsi); 311580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Push(proxy->name()); 311680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 311759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 311859151504615d929945dc59db37bf1166937748c6Steve Block 31190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 312180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // This expression cannot throw a reference error at the top level. 31220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Visit(expr); 312380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 312480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 312580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 312680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 312780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::TryLiteralCompare(Token::Value op, 312880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 312980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right, 313080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 313180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 313280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 313380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (op != Token::EQ && op != Token::EQ_STRICT) return false; 313480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 313580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for the pattern: typeof <expression> == <string literal>. 313680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Literal* right_literal = right->AsLiteral(); 313780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (right_literal == NULL) return false; 313880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<Object> right_literal_value = right_literal->handle(); 313980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (!right_literal_value->IsString()) return false; 314080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UnaryOperation* left_unary = left->AsUnaryOperation(); 314180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 314280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<String> check = Handle<String>::cast(right_literal_value); 314380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 31440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 31450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(left_unary->expression()); 31460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 31470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 314880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (check->Equals(Heap::number_symbol())) { 314980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Condition is_smi = masm_->CheckSmi(rax); 315080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(is_smi, if_true); 315180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 315280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 315380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 315480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::string_symbol())) { 315580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Condition is_smi = masm_->CheckSmi(rax); 315680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(is_smi, if_false); 315780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 315880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 315980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 316080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 316180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, if_false); 316280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpInstanceType(rdx, FIRST_NONSTRING_TYPE); 316380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(below, if_true, if_false, fall_through); 316480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::boolean_symbol())) { 316580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kTrueValueRootIndex); 3166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 316780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kFalseValueRootIndex); 316880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 316980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::undefined_symbol())) { 317080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 3171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 317280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Condition is_smi = masm_->CheckSmi(rax); 317380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(is_smi, if_false); 317480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 317580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 317680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 317780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 317880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 317980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::function_symbol())) { 318080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Condition is_smi = masm_->CheckSmi(rax); 318180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(is_smi, if_false); 318280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); 318380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 318480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Regular expressions => 'function' (they are callable). 318580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpInstanceType(rdx, JS_REGEXP_TYPE); 318680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 318780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::object_symbol())) { 318880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Condition is_smi = masm_->CheckSmi(rax); 318980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(is_smi, if_false); 319080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kNullValueRootIndex); 319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 319280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Regular expressions => 'function', not 'object'. 319380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpObjectType(rax, JS_REGEXP_TYPE, rdx); 319480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_false); 319580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 319680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 3197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 319880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, if_false); 319980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for JS objects => true. 320080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpInstanceType(rdx, FIRST_JS_OBJECT_TYPE); 320180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(below, if_false); 320280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpInstanceType(rdx, LAST_JS_OBJECT_TYPE); 320380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(below_equal, if_true, if_false, fall_through); 320480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 320580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 3206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 320780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 320880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return true; 3209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3212d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 321480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 3215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 3217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 322180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 32220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 32230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 322480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 322580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // First we try a fast inlined version of the compare when one of 322680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // the operands is a literal. 322780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->op(); 322880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left = expr->left(); 322980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right = expr->right(); 323080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { 32310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 323280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return; 323380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 3234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 32350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 323680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 3237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 32380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 3239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CompareRoot(rax, Heap::kTrueValueRootIndex); 324180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 3242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 32433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 32450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 3246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 3247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 324980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns 0 for true. 325080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(zero, if_true, if_false, fall_through); 3251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 32550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 3256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = no_condition; 3257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 325880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 3259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 3260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 3261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 326280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::EQ: 3263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = equal; 3264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 3265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 3267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 3268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 3269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 3271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 3272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 3273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 3274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 3275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 3277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 3278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 3279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 3280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 3281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 3283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 3284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 3285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 3287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 3288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 3290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 32920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 32930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 329480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 329580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ JumpIfNotBothSmi(rax, rdx, &slow_case); 329680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiCompare(rdx, rax); 329780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, NULL); 329880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 329980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 3300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 33010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareFlags flags = inline_smi_code 33020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_SMI_COMPARE_IN_STUB 33030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_COMPARE_FLAGS; 33040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareStub stub(cc, strict, flags); 3305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 330780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, fall_through); 3308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 33093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 33103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 3312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 33130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 331780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 331880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Comment cmnt(masm_, "[ CompareToNull"); 331980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 332080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 332180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 332280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 33230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 33240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 332580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 33260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 332780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kNullValueRootIndex); 332880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (expr->is_strict()) { 332980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 333080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 333180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 333280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 333380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 333480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Condition is_smi = masm_->CheckSmi(rax); 333580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(is_smi, if_false); 333680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // It can be an undetectable object. 333780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 333880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 333980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 334080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 334180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 33420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 334380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 334480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 334580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3346d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 3347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 33480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 33520d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 33530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return rax; 33540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 33570d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return rsi; 33590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 33600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 33610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 33620d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { 33630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(mode == RelocInfo::CODE_TARGET || 33640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mode == RelocInfo::CODE_TARGET_CONTEXT); 33650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ call(ic, mode); 33660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 33670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // If we're calling a (keyed) load or store stub, we have to mark 33680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // the call as containing no inlined code so we will not attempt to 33690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // patch it. 33700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (ic->kind()) { 33710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case Code::LOAD_IC: 33720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case Code::KEYED_LOAD_IC: 33730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case Code::STORE_IC: 33740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case Code::KEYED_STORE_IC: 33750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ nop(); // Signals no inlined code. 33760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 33770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen default: 33780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Do nothing. 33790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 33800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 33810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3384d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(IsAligned(frame_offset, kPointerSize)); 3386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, frame_offset), value); 33873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 33883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 33893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3390d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 339159151504615d929945dc59db37bf1166937748c6Steve Block __ movq(dst, ContextOperand(rsi, context_index)); 3392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 3396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 3397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 3400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 3401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 3402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address on top of stack (smi encoded Code* delta) 3403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, Operand(rsp, 0)); 3404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 3405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subq(rdx, rcx); 3406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Integer32ToSmi(rdx, rdx); 3407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), rdx); 3408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 3409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 3410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 3414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 3415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 3416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 3417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 3418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address. 3419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, Operand(rsp, 0)); 3420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiToInteger32(rdx, rdx); 3421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 3422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ addq(rdx, rcx); 3423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), rdx); 3424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // And return. 3425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 3426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __ 3430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 34323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 3433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 3435