full-codegen-x64.cc revision 4515c472dc3e5ed2448a564600976759e569a0a8
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 303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h" 31d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h" 323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "debug.h" 33d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h" 343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h" 353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the 433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them. The actual argument count matches the 443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function. 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rdi: the JS function object being called (ie, ourselves) 483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsi: our context 493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rbp: our caller's frame pointer 503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsp: stack pointer (pointing to return address) 513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout. 544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block function_ = fun; 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SetFunctionPosition(fun); 573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (mode == PRIMARY) { 594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rbp); // Caller's frame pointer. 604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rbp, rsp); 614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rsi); // Callee's context. 624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); // Callee's JS Function. 634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke { Comment cmnt(masm_, "[ Allocate locals"); 654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int locals_count = fun->scope()->num_stack_slots(); 664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (locals_count == 1) { 674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else if (locals_count > 1) { 694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < locals_count; i++) { 714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdx); 724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 73d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 74d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 75d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool function_in_register = true; 774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Possibly allocate a local context. 794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (fun->scope()->num_heap_slots() > 0) { 804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate local context"); 814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Argument to NewContext is the function, which is still in rdi. 824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); 834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallRuntime(Runtime::kNewContext, 1); 844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke function_in_register = false; 854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Context is returned in both rax and rsi. It replaces the context 864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // passed to us. It's saved in the stack and kept live in rsi. 874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Copy any necessary parameters into the context. 904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int num_parameters = fun->scope()->num_parameters(); 914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < num_parameters; i++) { 924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Slot* slot = fun->scope()->parameter(i)->slot(); 934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (slot != NULL && slot->type() == Slot::CONTEXT) { 944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int parameter_offset = StandardFrameConstants::kCallerSPOffset + 954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (num_parameters - 1 - i) * kPointerSize; 964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Load parameter from stack. 974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rax, Operand(rbp, parameter_offset)); 984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Store it in the context. 994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int context_offset = Context::SlotOffset(slot->index()); 1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(Operand(rsi, context_offset), rax); 1014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Update the write barrier. This clobbers all involved 1024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // registers, so we have use a third register to avoid 1034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // clobbering rsi. 1044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rcx, rsi); 1054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(rcx, context_offset, rax, rbx); 1064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Possibly allocate an arguments object. 1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Variable* arguments = fun->scope()->arguments()->AsVariable(); 1124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (arguments != NULL) { 1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Arguments object must be allocated after the context object, in 1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // case the "arguments" or ".arguments" variables are in the context. 1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate arguments object"); 1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (function_in_register) { 1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); 1184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 1194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The receiver is just before the parameters on the caller's stack. 1224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ lea(rdx, Operand(rbp, StandardFrameConstants::kCallerSPOffset + 1234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke fun->num_parameters() * kPointerSize)); 1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdx); 1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ Push(Smi::FromInt(fun->num_parameters())); 1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Arguments to ArgumentsAccessStub: 1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // function, receiver address, parameter count. 1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The stub will rewrite receiver and parameter count if the previous 1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // stack frame was an arguments adapter frame. 1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 1314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 1324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Store new arguments object in both "arguments" and ".arguments" slots. 1334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rcx, rax); 1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(arguments->slot(), rax, rbx, rdx); 1354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Slot* dot_arguments_slot = 1364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke fun->scope()->arguments_shadow()->AsVariable()->slot(); 1374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(dot_arguments_slot, rcx, rbx, rdx); 138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke { Comment cmnt(masm_, "[ Declarations"); 142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitDeclarations(fun->scope()->declarations()); 143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 144e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Stack check"); 1463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label ok; 1473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 1483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &ok); 1493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block StackCheckStub stub; 1503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallStub(&stub); 1513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&ok); 1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceEnter, 0); 1563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Body"); 159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block VisitStatements(fun->body()); 161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit a 'return undefined' in case control fell off the end of the body. 1663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitReturnSequence(function_->end_position()); 168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitReturnSequence(int position) { 173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CodeGenerator::RecordPositions(masm_, position); 1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ RecordJSReturn(); 1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Do not use the leave instruction here because it is too short to 1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // patch with the code required by the debugger. 1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsp, rbp); 1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(rbp); 193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); 1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Add padding that will be overwritten by a debugger breakpoint. We 1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // (3 + 1 + 3). 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const int kPadding = Assembler::kJSReturnSequenceLength - 7; 1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < kPadding; ++i) { 2003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block masm_->int3(); 2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check that the size of the code used for returning matches what is 203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expected by the debugger. 204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(Assembler::kJSReturnSequenceLength, 205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 2063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif 2073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 2093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) { 212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Move value into place. 222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(reg); 228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For simplicity we always test the accumulator register. 234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { 255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand slot_operand = EmitSlotSearch(slot, result_register()); 263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), slot_operand); 266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Memory operands can be pushed directly. 269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(slot_operand); 270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 296d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { 297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(lit->handle()); 310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 335d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) { 336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), Operand(rsp, 0)); 367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 375d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count, 376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context, 377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register reg) { 378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!reg.is(rsp)); 380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), reg); 397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), reg); 417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), result_register()); 418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 426d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, 427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_true, 428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_false) { 429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(materialize_true, materialize_false); 434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::true_value()); 443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&done); 444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::false_value()); 446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::true_value()); 450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&done); 451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::false_value()); 453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::true_value()); 467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::true_value()); 470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::false_value()); 480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::false_value()); 483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) { 492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The value to test is in the accumulator. If the value might be needed 493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // on the stack (value/test and test/value contexts with a stack location 494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // desired), then the value is already duplicated on the stack. 495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, true_label_); 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, false_label_); 497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In value/test and test/value expression contexts with stack as the 499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // desired location, there is already an extra value on the stack. Use a 500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // label to discard it if unneeded. 501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label discard; 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_true = true_label_; 503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_false = false_label_; 504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &discard; 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &discard; 526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the inlined tests assumed by the stub. 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); 533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiCompare(result_register(), Smi::FromInt(0)); 540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(is_smi, if_true); 543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save a copy of the value if it may be needed and isn't already saved. 545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the ToBoolean stub for all other cases. 573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ToBooleanStub stub; 574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ testq(rax, rax); 577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The stub returns nonzero for true. Complete based on the context. 579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, true_label_); 587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, &discard); 594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, true_label_); 599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, &discard); 610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, false_label_); 615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(true_label_); 620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 625d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (slot->type()) { 627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOCAL: 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(rbp, SlotOffset(slot)); 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::CONTEXT: { 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int context_chain_length = 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke function_->scope()->ContextChainLength(slot->var()->scope()); 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadContext(scratch, context_chain_length); 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CodeGenerator::ContextOperand(scratch, slot->index()); 635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOOKUP: 637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(rax, 0); 641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) { 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(source, destination); 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(destination, location); 647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 650d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst, 651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register src, 652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2) { 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!scratch1.is(src) && !scratch2.is(src)); 656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(dst, scratch1); 657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(location, src); 658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (dst->type() == Slot::CONTEXT) { 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(scratch1, offset, src, scratch2); 662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 666d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = decl->proxy()->var(); 669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(var != NULL); // Must have been resolved. 670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Slot* slot = var->slot(); 671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = var->AsProperty(); 672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->mode() == Variable::CONST) { 678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); 680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (decl->fun() != NULL) { 681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(decl->fun(), kAccumulator); 682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); 692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rbx, 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX)); 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmpq(rbx, rsi); 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(equal, "Unexpected declaration in current context."); 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->mode() == Variable::CONST) { 700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kScratchRegister); 703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the hole value is in old space. 704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (decl->fun() != NULL) { 705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(decl->fun(), kAccumulator); 706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result_register()); 708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 7094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rbx, rsi); 7104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(rbx, offset, result_register(), rcx); 711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rsi); 716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(var->name()); 717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(decl->mode() == Variable::VAR || 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block decl->mode() == Variable::CONST); 720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PropertyAttributes attr = 721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block (decl->mode() == Variable::VAR) ? NONE : READ_ONLY; 722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(attr)); 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->mode() == Variable::CONST) { 728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ PushRoot(Heap::kTheHoleValueRootIndex); 729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (decl->fun() != NULL) { 730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(decl->fun(), kStack); 731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(0)); // no initial value! 733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->fun() != NULL || decl->mode() == Variable::CONST) { 741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->key(), kStack); 745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->fun() != NULL) { 747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(decl->fun(), kAccumulator); 748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); 750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Absence of a test rax instruction following the call 755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // indicates that none of the load was inlined. 756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Value in rax is ignored (declarations are statements). Receiver 759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // and key on stack are discarded. 760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(2); 761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 766d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 7673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rsi); // The context is the first argument. 7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(pairs); 7703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); 7713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 776d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ FunctionLiteral"); 7783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Build the function boilerplate and instantiate it. 780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<JSFunction> boilerplate = 781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Compiler::BuildBoilerplate(expr, script_, this); 7823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (HasStackOverflow()) return; 7833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(boilerplate->IsBoilerplate()); 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create a new closure. 7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rsi); 7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(boilerplate); 7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kNewClosure, 2); 790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 794d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->var(), context_); 797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 800d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var, 801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Four cases: non-this global variables, lookup slots, all other 803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // types of slots, and parameters that rewrite to explicit property 804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // accesses on the arguments object. 805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Slot* slot = var->slot(); 806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Property* property = var->AsProperty(); 807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (var->is_global() && !var->is_this()) { 8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "Global variable"); 8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use inline caching. Variable name is passed in rcx and the global 8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // object on the stack. 8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(CodeGenerator::GlobalObject()); 813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, var->name()); 8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 8153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // A test rax instruction following the call is used by the IC to 8173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // indicate that the inobject property case was inlined. Ensure there 8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is no test rax instruction here. 819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context, rax); 821d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 822d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 823d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Lookup slot"); 824d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rsi); // Context. 825d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ Push(var->name()); 826d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context, rax); 828d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 829d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL) { 830d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 831d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ? "Context slot" 832d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : "Stack slot"); 833e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, slot); 834d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 836d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Rewritten parameter"); 837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(property); 838d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Rewritten parameter accesses are of the form "slot[literal]". 839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the object is in a slot. 841e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NOT_NULL(object_var); 843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Slot* object_slot = object_var->slot(); 844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_slot); 845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the object. 847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand object_loc = EmitSlotSearch(object_slot, rax); 848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(object_loc); 849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the key is a smi. 851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key_literal = property->key()->AsLiteral(); 852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(key_literal); 853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(key_literal->handle()->IsSmi()); 854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the key. 856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(key_literal->handle()); 857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a keyed property load. 859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Notice: We must not have a "test rax, ..." instruction after the 862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // call. It is treated specially by the LoadIC code. 863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Drop key and object left on the stack by IC, and push the result. 865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(2, context, rax); 8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 870d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 8723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rdi = JS function. 8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rbx = literals array. 8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rax = regexp literal. 8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rax, FieldOperand(rbx, literal_offset)); 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &done); 8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create regexp literal using runtime function 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Result will be in rax. 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rbx); 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->pattern()); 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->flags()); 8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&done); 892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 899e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(expr->literal_index())); 901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(expr->constant_properties()); 902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->depth() > 1) { 903e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateObjectLiteral, 3); 9043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); 906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in rax. 910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Save result on the stack 920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::CONSTANT: 924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kAccumulator); 931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, key->handle()); 9324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kSetProperty, 3); 944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::SETTER: 946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::GETTER: 947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(property->kind() == ObjectLiteral::Property::SETTER ? 950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(1) : 951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(0)); 952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDefineAccessor, 4); 954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 9643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 966d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 9673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 9683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 969e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 9703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(expr->constant_elements()); 9723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (expr->depth() > 1) { 973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 9763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* subexprs = expr->values(); 9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0, len = subexprs->length(); i < len; i++) { 9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 9873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 9893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 9933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 9953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(subexpr, kAccumulator); 9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Store the subexpression value in the array's elements. 9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(FieldOperand(rbx, offset), result_register()); 10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Update the write barrier for the array store. 1005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(rbx, offset, result_register(), rcx); 10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1009e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 10123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1016d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, key->handle()); 1020e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1025e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1027e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1031e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1032e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1033e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 1035e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1036e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1037e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(op, 1038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 1039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_GENERIC_BINARY_FLAGS); 1040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 1041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, rax); 1042e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1043e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1045d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 1046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1047d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Three main cases: non-this global variables, lookup slots, and 1048d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // all other types of slots. Left-hand-side parameters that rewrite 1049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // to explicit property accesses do not reach here. 10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var->is_global() || var->slot() != NULL); 1052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Slot* slot = var->slot(); 10533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1054d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1056d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in rax, variable name in 10574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // rcx, and the global object in rdx. 10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Move(rcx, var->name()); 10594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, CodeGenerator::GlobalObject()); 10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 10613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 10624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context, rax); 1063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1064d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1065d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(result_register()); // Value. 1066d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rsi); // Context. 1067d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ Push(var->name()); 1068d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1069d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context, rax); 1070d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (var->slot() != NULL) { 1072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 1076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, rcx); 1080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(target, result_register()); 1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // RecordWrite may destroy all its register arguments. 1083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 1084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1085e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(rcx, offset, rdx, rbx); 1086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1089d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, result_register()); 1094d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1095e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Variables rewritten as properties are not treated as variables in 1097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // assignments. 1098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1103d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1112d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, kPointerSize)); // Receiver is now under value. 1115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, prop->key()->AsLiteral()->handle()); 11224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (expr->ends_initialization_block()) { 11234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 11244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 11254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 11264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 11374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke DropAndApply(1, context_, rax); 11384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 11394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 1140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, 2 * kPointerSize)); 1154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1155e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1158e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1159e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This nop signals to the IC that there is no inlined code at the call 1163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // site for it to patch. 1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is under the key and value. 1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, 2 * kPointerSize)); 1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Receiver and key are still on stack. 1176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(2, context_, rax); 1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Evaluate receiver. 1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->obj(), kStack); 1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Drop receiver left on the stack by IC. 1190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->key(), kStack); 1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Drop key and receiver left on the stack by IC. 1195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(2, context_, rax); 1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 1201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Object> ignored, 1202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 1207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SetSourcePosition(expr->position()); 12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 1212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke in_loop); 1215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, mode); 1216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Discard the function left on TOS. 1219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 1220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 1224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 1225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 1231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); 1233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 12363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Discard the function left on TOS. 1237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 1238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1241d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 1242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 1243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 1245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 1247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to the identifier 'eval'. 1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a global variable. 1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(var->name()); 1252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object as receiver for the call IC lookup. 1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && var->slot() != NULL && 1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block var->slot()->type() == Slot::LOOKUP) { 1257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a lookup slot. 1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 1260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 1261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 1262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 1263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 1264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 1265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(key->handle()); 1266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a keyed property, use keyed load IC followed by function 1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // call. 1271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->key(), kStack); 1273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source code position for IC call. 1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(prop->position()); 1275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // By emitting a nop we make sure that we do not have a "test rax,..." 1278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // instruction after the call it is treated specially by the LoadIC code. 1279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 1280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Drop key left on the stack by IC. 1281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 1282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Pop receiver. 1283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rbx); 1284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push result (function). 1285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); 1286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push receiver object on stack. 1287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (prop->is_synthetic()) { 1288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rcx, CodeGenerator::GlobalObject()); 1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 1290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rbx); 1292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 1294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 1297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 1298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // also use the fast code generator. 1299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 1300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 1301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 1302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 1303d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 1304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(fun, kStack); 1306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 1307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rbx, CodeGenerator::GlobalObject()); 1308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 1309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 1310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 1311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 1320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push function on the stack. 1321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 1322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object (receiver). 1324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load function, arg_count into rdi and rax. 1338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(rax, arg_count); 1339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Function is in rsp[arg_count + 1]. 1340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); 1341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Replace function on TOS with result in rax, or pop it. 1346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 1355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(expr->name()); 1357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rax, CodeGenerator::GlobalObject()); 1358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 1359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 13603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 1364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 1368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the JS runtime function. 1369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block NOT_IN_LOOP); 1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Discard the function left on TOS. 1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 1378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1383d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 1385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 1387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 1388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 1395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 1397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 1398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 1400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 1401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 1405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Value is false so it's needed. 1406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 1407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 1408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 1409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 1411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 1412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through. 1415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 1417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 1418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 1425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label materialize_true, materialize_false, done; 1426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Initially assume a pure test context. Notice that the labels are 1427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // swapped. 1428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_true = false_label_; 1429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_false = true_label_; 1430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 1435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &done; 1436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &done; 1437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 1439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &materialize_false; 1440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &materialize_true; 1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 1443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 1445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &materialize_true; 1446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 1448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &materialize_false; 1449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForControl(expr->expression(), if_true, if_false); 1452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_false, if_true); // Labels swapped. 1453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (proxy != NULL && 1460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block !proxy->var()->is_this() && 1461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->is_global()) { 1462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "Global variable"); 1463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, proxy->name()); 1465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Use a regular load, not a contextual load, to avoid a reference 1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // error. 1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(Operand(rsp, 0), rax); 1470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (proxy != NULL && 1471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot() != NULL && 1472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot()->type() == Slot::LOOKUP) { 1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rsi); 1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(proxy->name()); 1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 1476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); 1477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This expression cannot throw a reference error at the top level. 1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 1480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 1484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 1488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 1489d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke VisitForValue(expr->expression(), kAccumulator); 1490d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 14914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 1492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &no_conversion); 1493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(result_register()); 1494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 1495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 1496d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context_, result_register()); 1497d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 1498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 15004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 15014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 15024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool overwrite = 15034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 15044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 15054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::SUB, overwrite); 15064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 15074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register rax. 15084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 15094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 15104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 15114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 15124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 15134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 15144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 15154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 15164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool overwrite = 15174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 15184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 15194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); 15204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 15214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register rax. 15224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 15234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Avoid calling the stub for Smis. 15244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Label smi, done; 15254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 15264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ j(is_smi, &smi); 15274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Non-smi: call stub leaving result in accumulator register. 15284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 15294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ jmp(&done); 15304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Perform operation directly on Smis. 15314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&smi); 15324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ SmiNot(result_register(), result_register()); 15334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 15344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, result_register()); 15354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 15364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 15374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 15423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 1545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Comment cmnt(masm_, "[ CountOperation"); 1546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 1548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 1551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 1552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 1553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 1554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 1555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 1556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 1560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 1561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 1562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Location saved_location = location_; 1563d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke location_ = kAccumulator; 1564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 1565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kValue); 1566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke location_ = saved_location; 1567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 1569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix() && context_ != Expression::kEffect) { 1570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Smi::FromInt(0)); 1571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 1574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 1575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->key(), kStack); 1577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 1578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1581d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 1582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 1583d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Condition is_smi; 1584d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke is_smi = masm_->CheckSmi(rax); 1585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &no_conversion); 1586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rax); 1587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 1588d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 1589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 1591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 1592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 1593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 1594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 1595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 1596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do not save result. 1597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 1599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 1600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 1601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 1602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the result on the stack. If we have a named or keyed property 1603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // we store the result under the receiver that is currently on top 1604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the stack. 1605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 1606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 1607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(rax); 1608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: 1610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, kPointerSize), rax); 1611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: 1613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 2 * kPointerSize), rax); 1614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1620d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 1621d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 1622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (loop_depth() > 0) { 1623d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 1624d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 1625d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1626d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 1627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(overflow, &stub_call); 1629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 1630d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 1631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke is_smi = masm_->CheckSmi(rax); 1632d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &done); 1633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 1634d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 1635d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 1636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 1637d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 1639d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 1642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(expr->binary_op(), 1643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 1644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_GENERIC_BINARY_FLAGS); 16454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke stub.GenerateCall(masm_, rax, Smi::FromInt(1)); 1646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 1647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in rax. 1649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 1650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 1651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 1652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kEffect); 1654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 1657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke context_); 1662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 1665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, prop->key()->AsLiteral()->handle()); 16664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 1667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // This nop signals to the IC that there is no inlined code at the call 1670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // site for it to patch. 1671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 1673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 1674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 16774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 1678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 1682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // This nop signals to the IC that there is no inlined code at the call 1685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // site for it to patch. 1686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 1688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(2); // Result is on the stack under the key and the receiver. 1689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(2, context_, rax); 1694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1700d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 1701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ BinaryOperation"); 1702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 1703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::COMMA: 1704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->left()); 1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Visit(expr->right()); 1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::OR: 1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::AND: 1710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitLogicalOperation(expr); 1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::ADD: 1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SUB: 1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::DIV: 1716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MOD: 1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MUL: 1718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_OR: 1719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_AND: 1720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_XOR: 1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHL: 1722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHR: 1723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::SAR: 1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitBinaryOp(expr->op(), context_); 1727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 1730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 17313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 17333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1735d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 1737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 1739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label materialize_true, materialize_false, done; 1741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Initially assume we are in a test context. 1742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_true = true_label_; 1743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_false = false_label_; 1744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 1745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 1746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 1749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &done; 1750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &done; 1751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 1753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &materialize_true; 1754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &materialize_false; 1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 1757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 1759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &materialize_true; 1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 1762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &materialize_false; 1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 17643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 1768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 1769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 1770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 1771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CompareRoot(rax, Heap::kTrueValueRootIndex); 1772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 1773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 1774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 17753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 1777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 1778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 1779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 1780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 1781e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, if_true); // The stub returns 0 for true. 1782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 1783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 1787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 1788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = no_condition; 1789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 1790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 1791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 1792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 1793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ: 1795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = equal; 1796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 1797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 1799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 1800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 1801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 1804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 1805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 1809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 1810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 1811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 1812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 1815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The comparison stub expects the smi vs. smi case to be handled 1825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // before it is called. 1826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label slow_case; 1827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ JumpIfNotBothSmi(rax, rdx, &slow_case); 1828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ SmiCompare(rdx, rax); 1829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(cc, if_true); 1830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&slow_case); 1833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CompareStub stub(cc, strict); 1834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 1835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(cc, if_true); 1837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 1838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 18393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1841e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 1842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 1843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_true, if_false); 1844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1847d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 1848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 1850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1853d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return rax; } 1854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1856d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return rsi; } 1857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1859d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 1860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(IsAligned(frame_offset, kPointerSize)); 1861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, frame_offset), value); 18623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1865d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 1866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index)); 1867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 1871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 1872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 1875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 1876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 1877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address on top of stack (smi encoded Code* delta) 1878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, Operand(rsp, 0)); 1879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 1880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subq(rdx, rcx); 1881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Integer32ToSmi(rdx, rdx); 1882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), rdx); 1883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 1884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 1889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 1890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 1891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 1892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address. 1894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, Operand(rsp, 0)); 1895e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiToInteger32(rdx, rdx); 1896e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 1897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ addq(rdx, rcx); 1898e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), rdx); 1899e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // And return. 1900e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __ 1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 19073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 1908