full-codegen-x64.cc revision 402d937239b0e2fd11bf2f4fe972ad78aa9fd481
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. 543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) { 553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(info_ == NULL); 563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu info_ = info; 573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (mode == PRIMARY) { 604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rbp); // Caller's frame pointer. 614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rbp, rsp); 624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rsi); // Callee's context. 634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); // Callee's JS Function. 644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke { Comment cmnt(masm_, "[ Allocate locals"); 663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int locals_count = scope()->num_stack_slots(); 674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (locals_count == 1) { 684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else if (locals_count > 1) { 704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < locals_count; i++) { 724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdx); 734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 74d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 75d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 76d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool function_in_register = true; 784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Possibly allocate a local context. 803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (scope()->num_heap_slots() > 0) { 814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate local context"); 824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Argument to NewContext is the function, which is still in rdi. 834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); 844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallRuntime(Runtime::kNewContext, 1); 854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke function_in_register = false; 864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Context is returned in both rax and rsi. It replaces the context 874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // passed to us. It's saved in the stack and kept live in rsi. 884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Copy any necessary parameters into the context. 913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int num_parameters = scope()->num_parameters(); 924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < num_parameters; i++) { 933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Slot* slot = scope()->parameter(i)->slot(); 944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (slot != NULL && slot->type() == Slot::CONTEXT) { 954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int parameter_offset = StandardFrameConstants::kCallerSPOffset + 964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (num_parameters - 1 - i) * kPointerSize; 974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Load parameter from stack. 984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rax, Operand(rbp, parameter_offset)); 994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Store it in the context. 1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int context_offset = Context::SlotOffset(slot->index()); 1014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(Operand(rsi, context_offset), rax); 1024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Update the write barrier. This clobbers all involved 1034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // registers, so we have use a third register to avoid 1044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // clobbering rsi. 1054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rcx, rsi); 1064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(rcx, context_offset, rax, rbx); 1074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Possibly allocate an arguments object. 1123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Variable* arguments = scope()->arguments()->AsVariable(); 1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (arguments != NULL) { 1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Arguments object must be allocated after the context object, in 1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // case the "arguments" or ".arguments" variables are in the context. 1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate arguments object"); 1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (function_in_register) { 1184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); 1194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 1204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The receiver is just before the parameters on the caller's stack. 1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int offset = scope()->num_parameters() * kPointerSize; 1243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ lea(rdx, 1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdx); 1273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ Push(Smi::FromInt(scope()->num_parameters())); 1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Arguments to ArgumentsAccessStub: 1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // function, receiver address, parameter count. 1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The stub will rewrite receiver and parameter count if the previous 1314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // stack frame was an arguments adapter frame. 1324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 1334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Store new arguments object in both "arguments" and ".arguments" slots. 1354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rcx, rax); 1364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(arguments->slot(), rax, rbx, rdx); 1374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Slot* dot_arguments_slot = 1383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->arguments_shadow()->AsVariable()->slot(); 1394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(dot_arguments_slot, rcx, rbx, rdx); 140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke { Comment cmnt(masm_, "[ Declarations"); 1443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu VisitDeclarations(scope()->declarations()); 145e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Stack check"); 1483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label ok; 1493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 1503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &ok); 1513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block StackCheckStub stub; 1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallStub(&stub); 1533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&ok); 1543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceEnter, 0); 1583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Body"); 161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu VisitStatements(function()->body()); 163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit a 'return undefined' in case control fell off the end of the body. 1683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu EmitReturnSequence(function()->end_position()); 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitReturnSequence(int position) { 175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CodeGenerator::RecordPositions(masm_, position); 1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ RecordJSReturn(); 1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Do not use the leave instruction here because it is too short to 1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // patch with the code required by the debugger. 1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsp, rbp); 1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(rbp); 1953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ ret((scope()->num_parameters() + 1) * kPointerSize); 1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Add padding that will be overwritten by a debugger breakpoint. We 1983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // (3 + 1 + 3). 200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const int kPadding = Assembler::kJSReturnSequenceLength - 7; 2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < kPadding; ++i) { 2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block masm_->int3(); 2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check that the size of the code used for returning matches what is 205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expected by the debugger. 206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(Assembler::kJSReturnSequenceLength, 207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 2083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif 2093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) { 214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Move value into place. 224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(reg); 230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For simplicity we always test the accumulator register. 236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { 257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand slot_operand = EmitSlotSearch(slot, result_register()); 265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), slot_operand); 268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Memory operands can be pushed directly. 271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(slot_operand); 272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 298d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(lit->handle()); 312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 337d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) { 338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), Operand(rsp, 0)); 369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 377d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count, 378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context, 379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register reg) { 380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!reg.is(rsp)); 382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), reg); 399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), reg); 419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), result_register()); 420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 428d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, 429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_true, 430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_false) { 431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(materialize_true, materialize_false); 436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::true_value()); 445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&done); 446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::false_value()); 448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::true_value()); 452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&done); 453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::false_value()); 455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::true_value()); 469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::true_value()); 472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::false_value()); 482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::false_value()); 485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) { 494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The value to test is in the accumulator. If the value might be needed 495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // on the stack (value/test and test/value contexts with a stack location 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // desired), then the value is already duplicated on the stack. 497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, true_label_); 498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, false_label_); 499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In value/test and test/value expression contexts with stack as the 501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // desired location, there is already an extra value on the stack. Use a 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // label to discard it if unneeded. 503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label discard; 504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_true = true_label_; 505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_false = false_label_; 506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &discard; 519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &discard; 528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the inlined tests assumed by the stub. 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); 535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); 539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiCompare(result_register(), Smi::FromInt(0)); 542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(is_smi, if_true); 545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save a copy of the value if it may be needed and isn't already saved. 547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the ToBoolean stub for all other cases. 575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ToBooleanStub stub; 576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ testq(rax, rax); 579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The stub returns nonzero for true. Complete based on the context. 581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, true_label_); 589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, &discard); 596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, true_label_); 601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, &discard); 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, false_label_); 617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(true_label_); 622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (slot->type()) { 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOCAL: 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(rbp, SlotOffset(slot)); 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::CONTEXT: { 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int context_chain_length = 6343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->ContextChainLength(slot->var()->scope()); 635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadContext(scratch, context_chain_length); 636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CodeGenerator::ContextOperand(scratch, slot->index()); 637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOOKUP: 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(rax, 0); 643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) { 647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(source, destination); 648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(destination, location); 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 652d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst, 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register src, 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2) { 656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!scratch1.is(src) && !scratch2.is(src)); 658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(dst, scratch1); 659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(location, src); 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (dst->type() == Slot::CONTEXT) { 662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(scratch1, offset, src, scratch2); 664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 668d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = decl->proxy()->var(); 671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(var != NULL); // Must have been resolved. 672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Slot* slot = var->slot(); 673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = var->AsProperty(); 674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->mode() == Variable::CONST) { 680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); 682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (decl->fun() != NULL) { 683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(decl->fun(), kAccumulator); 684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 6933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT_EQ(0, scope()->ContextChainLength(var->scope())); 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rbx, 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX)); 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmpq(rbx, rsi); 699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(equal, "Unexpected declaration in current context."); 700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->mode() == Variable::CONST) { 702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kScratchRegister); 705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the hole value is in old space. 706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (decl->fun() != NULL) { 707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(decl->fun(), kAccumulator); 708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result_register()); 710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 7114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rbx, rsi); 7124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(rbx, offset, result_register(), rcx); 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rsi); 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(var->name()); 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(decl->mode() == Variable::VAR || 721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block decl->mode() == Variable::CONST); 722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PropertyAttributes attr = 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block (decl->mode() == Variable::VAR) ? NONE : READ_ONLY; 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(attr)); 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->mode() == Variable::CONST) { 730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ PushRoot(Heap::kTheHoleValueRootIndex); 731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (decl->fun() != NULL) { 732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(decl->fun(), kStack); 733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(0)); // no initial value! 735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->fun() != NULL || decl->mode() == Variable::CONST) { 743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->key(), kStack); 747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (decl->fun() != NULL) { 749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(decl->fun(), kAccumulator); 750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); 752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Absence of a test rax instruction following the call 757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // indicates that none of the load was inlined. 758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Value in rax is ignored (declarations are statements). Receiver 761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // and key on stack are discarded. 762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(2); 763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 768d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 7703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rsi); // The context is the first argument. 7713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(pairs); 7723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ Push(Smi::FromInt(is_eval() ? 1 : 0)); 7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 778d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 7793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ FunctionLiteral"); 7803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Build the function boilerplate and instantiate it. 782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<JSFunction> boilerplate = 7833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Compiler::BuildBoilerplate(expr, script(), this); 7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (HasStackOverflow()) return; 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(boilerplate->IsBoilerplate()); 7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create a new closure. 7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rsi); 7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(boilerplate); 7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kNewClosure, 2); 792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 7933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 796d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->var(), context_); 799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var, 803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Four cases: non-this global variables, lookup slots, all other 805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // types of slots, and parameters that rewrite to explicit property 806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // accesses on the arguments object. 807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Slot* slot = var->slot(); 808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Property* property = var->AsProperty(); 809d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 810d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (var->is_global() && !var->is_this()) { 8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "Global variable"); 8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use inline caching. Variable name is passed in rcx and the global 8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // object on the stack. 8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(CodeGenerator::GlobalObject()); 815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, var->name()); 8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 8173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // A test rax instruction following the call is used by the IC to 8193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // indicate that the inobject property case was inlined. Ensure there 8203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is no test rax instruction here. 821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context, rax); 823d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 824d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 825d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Lookup slot"); 826d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rsi); // Context. 827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ Push(var->name()); 828d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 829d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context, rax); 830d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 831d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL) { 832d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 833d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ? "Context slot" 834d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : "Stack slot"); 835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, slot); 836d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 838d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Rewritten parameter"); 839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(property); 840d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Rewritten parameter accesses are of the form "slot[literal]". 841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the object is in a slot. 843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NOT_NULL(object_var); 845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Slot* object_slot = object_var->slot(); 846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_slot); 847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the object. 849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand object_loc = EmitSlotSearch(object_slot, rax); 850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(object_loc); 851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the key is a smi. 853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key_literal = property->key()->AsLiteral(); 854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(key_literal); 855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(key_literal->handle()->IsSmi()); 856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the key. 858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(key_literal->handle()); 859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a keyed property load. 861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Notice: We must not have a "test rax, ..." instruction after the 864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // call. It is treated specially by the LoadIC code. 865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Drop key and object left on the stack by IC, and push the result. 867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(2, context, rax); 8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rdi = JS function. 8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rbx = literals array. 8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rax = regexp literal. 8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rax, FieldOperand(rbx, literal_offset)); 8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &done); 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create regexp literal using runtime function 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Result will be in rax. 8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rbx); 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->pattern()); 8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->flags()); 8923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 8933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&done); 894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 898d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 901e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(expr->literal_index())); 903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(expr->constant_properties()); 904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->depth() > 1) { 905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateObjectLiteral, 3); 9063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 907e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); 908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in rax. 912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Save result on the stack 922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::CONSTANT: 926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kAccumulator); 933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, key->handle()); 9344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kSetProperty, 3); 946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::SETTER: 948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::GETTER: 949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(property->kind() == ObjectLiteral::Property::SETTER ? 952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(1) : 953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(0)); 954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDefineAccessor, 4); 956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 9643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 9663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 968d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 9693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 9703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 9723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(expr->constant_elements()); 9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (expr->depth() > 1) { 975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 9763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 9783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* subexprs = expr->values(); 9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0, len = subexprs->length(); i < len; i++) { 9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 9873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 9893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 9953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 9963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(subexpr, kAccumulator); 9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Store the subexpression value in the array's elements. 10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(FieldOperand(rbx, offset), result_register()); 10053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Update the write barrier for the array store. 1007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(rbx, offset, result_register(), rcx); 10083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1018402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1019402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1020402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(expr->op() != Token::INIT_CONST); 1021402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 1022402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1023402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1024402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 1025402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Property* prop = expr->target()->AsProperty(); 1026402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (prop != NULL) { 1027402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu assign_type = 1028402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1029402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1030402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1031402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1032402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1033402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1034402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1035402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1036402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1037402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1038402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 1039402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kAccumulator); 1040402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1041402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1042402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 1043402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1044402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1045402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1046402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 1047402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->key(), kStack); 1048402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1049402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1050402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1051402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Get value of LHS expression and 1052402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // store in on top of the stack. 1053402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1054402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1055402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kStack; 1056402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1057402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1058402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableLoad(expr->target()->AsVariableProxy()->var(), 1059402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression::kValue); 1060402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1061402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1062402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyLoad(prop); 1063402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1064402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1065402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1066402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyLoad(prop); 1067402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1068402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1069402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1070402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1071402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1072402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1073402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate RHS expression. 1074402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression* rhs = expr->value(); 1075402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(rhs, kAccumulator); 1076402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1077402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Apply operator. 1078402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1079402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1080402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kAccumulator; 1081402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitBinaryOp(expr->binary_op(), Expression::kValue); 1082402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1083402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1084402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1085402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1086402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1087402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1088402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1089402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1090402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1091402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1092402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu context_); 1093402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1094402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1095402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1096402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1097402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1098402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1099402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1100402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1101402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1102402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1103402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1104d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, key->handle()); 1108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 1123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1124e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(op, 1126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 1127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_GENERIC_BINARY_FLAGS); 1128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 1129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, rax); 1130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1133d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 1134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Three main cases: non-this global variables, lookup slots, and 1136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // all other types of slots. Left-hand-side parameters that rewrite 1137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // to explicit property accesses do not reach here. 11383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 11393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var->is_global() || var->slot() != NULL); 1140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Slot* slot = var->slot(); 11413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in rax, variable name in 11454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // rcx, and the global object in rdx. 11463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Move(rcx, var->name()); 11474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, CodeGenerator::GlobalObject()); 11483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 11493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 11504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context, rax); 1151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1153d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(result_register()); // Value. 1154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rsi); // Context. 1155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ Push(var->name()); 1156d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context, rax); 1158d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1159e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (var->slot() != NULL) { 1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 1162e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1163e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, rcx); 1168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(target, result_register()); 1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // RecordWrite may destroy all its register arguments. 1171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(rcx, offset, rdx, rbx); 1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 11753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 11803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, result_register()); 1182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1183e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Variables rewritten as properties are not treated as variables in 1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // assignments. 1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1191d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, kPointerSize)); // Receiver is now under value. 1203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, prop->key()->AsLiteral()->handle()); 12104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (expr->ends_initialization_block()) { 12114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 12124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 12134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 12144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 12254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke DropAndApply(1, context_, rax); 12264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 12274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 1228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, 2 * kPointerSize)); 1242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This nop signals to the IC that there is no inlined code at the call 1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // site for it to patch. 1252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is under the key and value. 1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, 2 * kPointerSize)); 1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Receiver and key are still on stack. 1264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(2, context_, rax); 1265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1268d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Evaluate receiver. 1273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->obj(), kStack); 1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 1276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 1277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Drop receiver left on the stack by IC. 1278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 1279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->key(), kStack); 1281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 1282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Drop key and receiver left on the stack by IC. 1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(2, context_, rax); 1284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1288d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 1289402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Object> name, 1290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 1291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 1292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 1295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Move(rcx, name); 1298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SetSourcePosition(expr->position()); 13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 1301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 13023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke in_loop); 1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, mode); 1305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, rax); 1308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 1312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 1313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 1319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); 1321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Discard the function left on TOS. 1325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 1326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1329d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 1330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 1331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 1332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 1333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 1335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to the identifier 'eval'. 1336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 1338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a global variable. 1339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object as receiver for the call IC lookup. 1340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && var->slot() != NULL && 1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block var->slot()->type() == Slot::LOOKUP) { 1344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a lookup slot. 1345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 1347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 1348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 1349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 1350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 1351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 1352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a keyed property, use keyed load IC followed by function 1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // call. 1357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->key(), kStack); 1359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source code position for IC call. 1360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(prop->position()); 1361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // By emitting a nop we make sure that we do not have a "test rax,..." 1364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // instruction after the call it is treated specially by the LoadIC code. 1365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 1366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Drop key left on the stack by IC. 1367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 1368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Pop receiver. 1369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rbx); 1370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push result (function). 1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); 1372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push receiver object on stack. 1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (prop->is_synthetic()) { 1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rcx, CodeGenerator::GlobalObject()); 1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rbx); 1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 13813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 1384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // also use the fast code generator. 1385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 1387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 1388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 1389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(fun, kStack); 1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rbx, CodeGenerator::GlobalObject()); 1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 1395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 1396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 1397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 1406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push function on the stack. 1407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 1408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object (receiver). 1410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load function, arg_count into rdi and rax. 1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(rax, arg_count); 1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Function is in rsp[arg_count + 1]. 1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); 1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Replace function on TOS with result in rax, or pop it. 1432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 14333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 14343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1436d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 14373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 14383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 14393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rax, CodeGenerator::GlobalObject()); 1443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 14453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 14473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 14483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 1449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 1453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Call the JS runtime function using a call IC. 1454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Move(rcx, expr->name()); 1455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 1462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, rax); 1464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1467d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 1470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 1471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 1472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 1477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 1480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 1481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 1482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 1484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 1485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 1489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Value is false so it's needed. 1490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 1491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 1493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 1495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 1496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through. 1499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 1500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 1501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 1502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 1508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 1509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label materialize_true, materialize_false, done; 1510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Initially assume a pure test context. Notice that the labels are 1511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // swapped. 1512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_true = false_label_; 1513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_false = true_label_; 1514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 1515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 1516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 1519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &done; 1520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &done; 1521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 1523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &materialize_false; 1524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &materialize_true; 1525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 1527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 1529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &materialize_true; 1530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &materialize_false; 1533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForControl(expr->expression(), if_true, if_false); 1536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_false, if_true); // Labels swapped. 1537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (proxy != NULL && 1544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block !proxy->var()->is_this() && 1545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->is_global()) { 1546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "Global variable"); 1547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, proxy->name()); 1549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Use a regular load, not a contextual load, to avoid a reference 1551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // error. 1552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(Operand(rsp, 0), rax); 1554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (proxy != NULL && 1555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot() != NULL && 1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot()->type() == Slot::LOOKUP) { 1557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rsi); 1558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(proxy->name()); 1559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 1560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); 1561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This expression cannot throw a reference error at the top level. 1563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 1564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 1567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 1568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1571d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 1572d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 1573d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke VisitForValue(expr->expression(), kAccumulator); 1574d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 15754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 1576d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &no_conversion); 1577d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(result_register()); 1578d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 1579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 1580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context_, result_register()); 1581d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 1582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1583d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 15844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 15854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 15864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool overwrite = 15874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 15884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 15894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::SUB, overwrite); 15904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 15914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register rax. 15924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 15934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 15944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 15954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 15964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 15974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 15984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 15994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 16004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool overwrite = 16014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 16024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 16034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); 16044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 16054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register rax. 16064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 16074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Avoid calling the stub for Smis. 16084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Label smi, done; 16094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 16104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ j(is_smi, &smi); 16114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Non-smi: call stub leaving result in accumulator register. 16124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 16134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ jmp(&done); 16144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Perform operation directly on Smis. 16154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&smi); 16164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ SmiNot(result_register(), result_register()); 16174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 16184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, result_register()); 16194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 16204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 16214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 1623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 16243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Comment cmnt(masm_, "[ CountOperation"); 1630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 1632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 1635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 1636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 1637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 1638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 1639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 1640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 1644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 1645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 1646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Location saved_location = location_; 1647d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke location_ = kAccumulator; 1648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 1649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kValue); 1650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke location_ = saved_location; 1651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 1653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix() && context_ != Expression::kEffect) { 1654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Smi::FromInt(0)); 1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 1658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->key(), kStack); 1661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 1662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1665d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 1666d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 1667d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Condition is_smi; 1668d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke is_smi = masm_->CheckSmi(rax); 1669d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &no_conversion); 1670d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rax); 1671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 1672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 1673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 1675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 1676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 1677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 1678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 1679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 1680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do not save result. 1681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 1683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 1684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 1685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 1686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the result on the stack. If we have a named or keyed property 1687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // we store the result under the receiver that is currently on top 1688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the stack. 1689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 1691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(rax); 1692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: 1694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, kPointerSize), rax); 1695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: 1697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 2 * kPointerSize), rax); 1698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 1705d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 1706d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (loop_depth() > 0) { 1707d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 1709d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1710d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 1711d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1712d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(overflow, &stub_call); 1713d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 1714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 1715d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke is_smi = masm_->CheckSmi(rax); 1716d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &done); 1717d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 1718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 1719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 1720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 1721d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1722d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 1723d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(expr->binary_op(), 1727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 1728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_GENERIC_BINARY_FLAGS); 17294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke stub.GenerateCall(masm_, rax, Smi::FromInt(1)); 1730d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 1731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in rax. 1733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 1734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 1736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kEffect); 1738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 1739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 1741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke context_); 1746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 1749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, prop->key()->AsLiteral()->handle()); 17504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 1751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // This nop signals to the IC that there is no inlined code at the call 1754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // site for it to patch. 1755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 1757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 1758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 17614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 1762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 1766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // This nop signals to the IC that there is no inlined code at the call 1769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // site for it to patch. 1770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 1772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(2); // Result is on the stack under the key and the receiver. 1773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 1774e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(2, context_, rax); 1778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1781e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1784d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 1785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ BinaryOperation"); 1786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 1787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::COMMA: 1788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->left()); 1789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Visit(expr->right()); 1790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::OR: 1793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::AND: 1794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitLogicalOperation(expr); 1795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::ADD: 1798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SUB: 1799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::DIV: 1800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MOD: 1801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MUL: 1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_OR: 1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_AND: 1804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_XOR: 1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHL: 1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHR: 1807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::SAR: 1808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 1809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 1810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitBinaryOp(expr->op(), context_); 1811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 18153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 18173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1819d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 1821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 1823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 1824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label materialize_true, materialize_false, done; 1825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Initially assume we are in a test context. 1826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_true = true_label_; 1827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_false = false_label_; 1828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 1830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 1833e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &done; 1834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &done; 1835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 1837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &materialize_true; 1838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &materialize_false; 1839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 1841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 1843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &materialize_true; 1844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 1846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &materialize_false; 1847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 1852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 1853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 1854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 1855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CompareRoot(rax, Heap::kTrueValueRootIndex); 1856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 1857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 1858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 18593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 1861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 1862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 1863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 1864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 1865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, if_true); // The stub returns 0 for true. 1866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 1871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 1872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = no_condition; 1873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 1874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 1875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 1876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 1877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ: 1879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = equal; 1880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 1881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 1883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 1884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 1885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 1887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 1888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 1889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 1890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 1893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 1894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 1895e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 1899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 1900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The comparison stub expects the smi vs. smi case to be handled 1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // before it is called. 1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label slow_case; 1911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ JumpIfNotBothSmi(rax, rdx, &slow_case); 1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ SmiCompare(rdx, rax); 1913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(cc, if_true); 1914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 1915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&slow_case); 1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CompareStub stub(cc, strict); 1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 1920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(cc, if_true); 1921e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 19233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 19243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 1926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 1927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_true, if_false); 1928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1931d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 1932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 1934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1937d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return rax; } 1938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1940d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return rsi; } 1941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1943d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 1944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(IsAligned(frame_offset, kPointerSize)); 1945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, frame_offset), value); 19463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 19473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 19483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1949d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 1950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index)); 1951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 1955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 1956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1958d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 1959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 1960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 1961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address on top of stack (smi encoded Code* delta) 1962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, Operand(rsp, 0)); 1963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 1964e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subq(rdx, rcx); 1965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Integer32ToSmi(rdx, rdx); 1966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), rdx); 1967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 1968e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1969e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1972d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 1973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 1974e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 1975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 1976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address. 1978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, Operand(rsp, 0)); 1979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiToInteger32(rdx, rdx); 1980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 1981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ addq(rdx, rcx); 1982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), rdx); 1983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // And return. 1984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 1985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __ 1989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 19913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 1992