full-codegen-x64.cc revision bb769b257e753aafcbd96767abb2abc645eaa20c
14515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// Copyright 2010 the V8 project authors. All rights reserved. 23ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Redistribution and use in source and binary forms, with or without 33ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// modification, are permitted provided that the following conditions are 43ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// met: 53ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 63ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Redistributions of source code must retain the above copyright 73ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// notice, this list of conditions and the following disclaimer. 83ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Redistributions in binary form must reproduce the above 93ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// copyright notice, this list of conditions and the following 103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// disclaimer in the documentation and/or other materials provided 113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// with the distribution. 123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Neither the name of Google Inc. nor the names of its 133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// contributors may be used to endorse or promote products derived 143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// from this software without specific prior written permission. 153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "v8.h" 293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h" 33d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h" 343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "debug.h" 35d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h" 363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h" 376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h" 383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the 463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them. The actual argument count matches the 473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function. 483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rdi: the JS function object being called (ie, ourselves) 513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsi: our context 523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rbp: our caller's frame pointer 533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsp: stack pointer (pointing to return address) 543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout. 573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) { 583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(info_ == NULL); 593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu info_ = info; 603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (mode == PRIMARY) { 644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rbp); // Caller's frame pointer. 654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rbp, rsp); 664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rsi); // Callee's context. 674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); // Callee's JS Function. 684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke { Comment cmnt(masm_, "[ Allocate locals"); 703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int locals_count = scope()->num_stack_slots(); 714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (locals_count == 1) { 724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else if (locals_count > 1) { 744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < locals_count; i++) { 764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdx); 774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 78d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 79d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 80d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool function_in_register = true; 824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Possibly allocate a local context. 84f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 85f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (heap_slots > 0) { 864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate local context"); 874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Argument to NewContext is the function, which is still in rdi. 884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); 89f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (heap_slots <= FastNewContextStub::kMaximumSlots) { 90f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastNewContextStub stub(heap_slots); 91f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 92f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 93f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kNewContext, 1); 94f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke function_in_register = false; 964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Context is returned in both rax and rsi. It replaces the context 974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // passed to us. It's saved in the stack and kept live in rsi. 984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Copy any necessary parameters into the context. 1013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int num_parameters = scope()->num_parameters(); 1024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < num_parameters; i++) { 1033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Slot* slot = scope()->parameter(i)->slot(); 1044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (slot != NULL && slot->type() == Slot::CONTEXT) { 1054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int parameter_offset = StandardFrameConstants::kCallerSPOffset + 1064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (num_parameters - 1 - i) * kPointerSize; 1074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Load parameter from stack. 1084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rax, Operand(rbp, parameter_offset)); 1094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Store it in the context. 1104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int context_offset = Context::SlotOffset(slot->index()); 1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(Operand(rsi, context_offset), rax); 1124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Update the write barrier. This clobbers all involved 1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // registers, so we have use a third register to avoid 1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // clobbering rsi. 1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rcx, rsi); 1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(rcx, context_offset, rax, rbx); 1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Possibly allocate an arguments object. 1223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Variable* arguments = scope()->arguments()->AsVariable(); 1234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (arguments != NULL) { 1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Arguments object must be allocated after the context object, in 1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // case the "arguments" or ".arguments" variables are in the context. 1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate arguments object"); 1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (function_in_register) { 1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdi); 1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The receiver is just before the parameters on the caller's stack. 1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int offset = scope()->num_parameters() * kPointerSize; 1343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ lea(rdx, 1353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 1364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdx); 1373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ Push(Smi::FromInt(scope()->num_parameters())); 1384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Arguments to ArgumentsAccessStub: 1394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // function, receiver address, parameter count. 1404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The stub will rewrite receiver and parameter count if the previous 1414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // stack frame was an arguments adapter frame. 1424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 1434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 1444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Store new arguments object in both "arguments" and ".arguments" slots. 1454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rcx, rax); 1464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(arguments->slot(), rax, rbx, rdx); 1474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Slot* dot_arguments_slot = 1483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->arguments_shadow()->AsVariable()->slot(); 1494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(dot_arguments_slot, rcx, rbx, rdx); 150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke { Comment cmnt(masm_, "[ Declarations"); 154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // For named function expressions, declare the function name as a 155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant. 156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && scope()->function() != NULL) { 157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(scope()->function(), Variable::CONST, NULL); 158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Visit all the explicit declarations unless there is an illegal 160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // redeclaration. 161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->HasIllegalRedeclaration()) { 162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke scope()->VisitIllegalRedeclaration(this); 163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitDeclarations(scope()->declarations()); 165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 166e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Stack check"); 1693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label ok; 1703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &ok); 1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block StackCheckStub stub; 1733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallStub(&stub); 1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&ok); 1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceEnter, 0); 1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Body"); 182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu VisitStatements(function()->body()); 184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit a 'return undefined' in case control fell off the end of the body. 1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 2043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 210bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ RecordJSReturn(); 2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Do not use the leave instruction here because it is too short to 2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // patch with the code required by the debugger. 2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsp, rbp); 2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(rbp); 2163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ ret((scope()->num_parameters() + 1) * kPointerSize); 2173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Add padding that will be overwritten by a debugger breakpoint. We 2193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 2203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // (3 + 1 + 3). 221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const int kPadding = Assembler::kJSReturnSequenceLength - 7; 2223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < kPadding; ++i) { 2233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block masm_->int3(); 2243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check that the size of the code used for returning matches what is 226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expected by the debugger. 227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(Assembler::kJSReturnSequenceLength, 228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 2293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif 2303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 2323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 234d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) { 235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Move value into place. 245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(reg); 251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For simplicity we always test the accumulator register. 257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 277d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { 278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand slot_operand = EmitSlotSearch(slot, result_register()); 286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), slot_operand); 289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Memory operands can be pushed directly. 292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(slot_operand); 293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 319d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { 320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(lit->handle()); 333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), lit->handle()); 345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 358d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) { 359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), Operand(rsp, 0)); 390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count, 399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context, 400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register reg) { 401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!reg.is(rsp)); 403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), reg); 420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ movq(result_register(), reg); 436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(result_register(), reg); 440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), result_register()); 441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::PrepareTest(Label* materialize_true, 450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* materialize_false, 451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label** if_true, 452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label** if_false) { 453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (context_) { 454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kUninitialized: 455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke UNREACHABLE(); 456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kEffect: 458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In an effect context, the true and the false case branch to the 459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // same label. 460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = *if_false = materialize_true; 461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValue: 463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = materialize_true; 464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = materialize_false; 465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTest: 467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = true_label_; 468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = false_label_; 469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValueTest: 471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = materialize_true; 472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = false_label_; 473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTestValue: 475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = true_label_; 476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = materialize_false; 477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 482d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, 483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_true, 484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_false) { 485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(materialize_true, materialize_false); 490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::true_value()); 499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&done); 500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::false_value()); 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::true_value()); 506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&done); 507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::false_value()); 509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::true_value()); 523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::true_value()); 526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(result_register(), Factory::false_value()); 536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Factory::false_value()); 539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Convert constant control flow (true or false) to the result expected for 548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// a given expression context. 549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, bool flag) { 550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (context) { 551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kUninitialized: 552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke UNREACHABLE(); 553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kEffect: 555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValue: { 557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Heap::RootListIndex value_root_index = 558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(result_register(), value_root_index); 562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PushRoot(value_root_index); 565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTest: 570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(flag ? true_label_ : false_label_); 571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTestValue: 573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is false it's needed. 576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is false it's needed. 580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!flag) __ PushRoot(Heap::kFalseValueRootIndex); 581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(flag ? true_label_ : false_label_); 584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValueTest: 586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is true it's needed. 589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is true it's needed. 593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (flag) __ PushRoot(Heap::kTrueValueRootIndex); 594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(flag ? true_label_ : false_label_); 597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 602d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) { 603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The value to test is in the accumulator. If the value might be needed 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // on the stack (value/test and test/value contexts with a stack location 605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // desired), then the value is already duplicated on the stack. 606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, true_label_); 607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, false_label_); 608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In value/test and test/value expression contexts with stack as the 610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // desired location, there is already an extra value on the stack. Use a 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // label to discard it if unneeded. 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label discard; 613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_true = true_label_; 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_false = false_label_; 615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &discard; 628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &discard; 637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the inlined tests assumed by the stub. 643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); 644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); 648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiCompare(result_register(), Smi::FromInt(0)); 651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(is_smi, if_true); 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save a copy of the value if it may be needed and isn't already saved. 656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the ToBoolean stub for all other cases. 684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ToBooleanStub stub; 685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ testq(rax, rax); 688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The stub returns nonzero for true. Complete based on the context. 690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, true_label_); 698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, &discard); 705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, true_label_); 710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, &discard); 721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, false_label_); 726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(true_label_); 731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 736d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (slot->type()) { 738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOCAL: 740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(rbp, SlotOffset(slot)); 741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::CONTEXT: { 742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int context_chain_length = 7433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->ContextChainLength(slot->var()->scope()); 744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadContext(scratch, context_chain_length); 745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CodeGenerator::ContextOperand(scratch, slot->index()); 746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOOKUP: 748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(rax, 0); 752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 755d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) { 756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(source, destination); 757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(destination, location); 758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 761d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst, 762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register src, 763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2) { 765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!scratch1.is(src) && !scratch2.is(src)); 767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(dst, scratch1); 768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(location, src); 769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (dst->type() == Slot::CONTEXT) { 771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(scratch1, offset, src, scratch2); 773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable, 778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable::Mode mode, 779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FunctionLiteral* function) { 780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(variable != NULL); // Must have been resolved. 782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Slot* slot = variable->slot(); 783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = variable->AsProperty(); 784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); 792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 794e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rbx, 807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX)); 808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmpq(rbx, rsi); 809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(equal, "Unexpected declaration in current context."); 810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kScratchRegister); 815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the hole value is in old space. 816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result_register()); 820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 8214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rbx, rsi); 8224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(rbx, offset, result_register(), rcx); 823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rsi); 828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(variable->name()); 829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(mode == Variable::VAR || mode == Variable::CONST); 831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; 832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(attr)); 833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ PushRoot(Heap::kTheHoleValueRootIndex); 839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kStack); 841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(0)); // no initial value! 843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL || mode == Variable::CONST) { 851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL) { 855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kStack); 856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rcx); 858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kAccumulator); 860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, result_register()); 861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); 862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Absence of a test rax instruction following the call 868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // indicates that none of the load was inlined. 869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rsi); // The context is the first argument. 8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(pairs); 8843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ Push(Smi::FromInt(is_eval() ? 1 : 0)); 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(stmt->tag(), kStack); 896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(clause->label(), kAccumulator); 916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the comparison as if via '==='. The comparison stub expects 918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the smi vs. smi case to be handled before it is called. 919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_case; 920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 0)); // Switch value. 921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfNotBothSmi(rdx, rax, &slow_case); 922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiCompare(rdx, rax); 923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(clause->body_target()->entry_label()); 926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_case); 928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CompareStub stub(equal, true); 929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testq(rax, rax); 931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(clause->body_target()->entry_label()); 934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(nested_statement.break_target()); 942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(default_clause->body_target()->entry_label()); 944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(clause->body_target()->entry_label()); 951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(nested_statement.break_target()); 955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the object to enumerate over. Both SpiderMonkey and JSC 967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ignore null and undefined in contrast to the specification; see 968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ECMA-262 section 12.6.4. 969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(stmt->enumerable(), kAccumulator); 970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kNullValueRootIndex); 973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &convert); 978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, &done_convert); 980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // TODO(kasperl): Check cache validity in generated code. This is a 987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // fast case for the JSObject::IsSimpleEnum cache validity 988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // checks. If we cannot guarantee cache validity, call the runtime 989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // system to check cache validity or get the property names in a 990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // fixed array. 991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Duplicate the enumerable object on the stack. 994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label fixed_array; 1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Heap::kMetaMapRootIndex); 1002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &fixed_array); 1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register rax. Get the enumeration cache from it. 1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset)); 1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); 1007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Setup the four remaining stack slots. 1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Map. 1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rdx); // Enumeration cache. 1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); 1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Enumeration cache length (as smi). 1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Initial index. 1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register rax. Iterate through that. 1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Map (0) - force slow check. 1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 1021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 1022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Fixed array length (as smi). 1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Initial index. 1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. 1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. 1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, loop_statement.break_target()); 1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register rbx. 1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, Operand(rsp, 2 * kPointerSize)); 1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SmiIndex index = __ SmiToIndex(rax, rax, kPointerSizeLog2); 1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rbx, 1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize)); 1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the expected map from the stack or a zero map in the 1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register rdx. 1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 3 * kPointerSize)); 1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If not, we have to filter the key. 1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label update_each; 1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rcx, Operand(rsp, 4 * kPointerSize)); 1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); 1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &update_each); 1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the entry to a string or null if it isn't a property 1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // anymore. If the property has been removed while iterating, we 1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rcx); // Enumerable. 1054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rbx); // Current entry. 1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kNullValueRootIndex); 1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, loop_statement.continue_target()); 1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, rax); 1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register rbx. 1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(result_register(), rbx); 1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitAssignment(stmt->each()); 1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label stack_limit_hit, stack_check_done; 1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ StackLimitCheck(&stack_limit_hit); 1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_check_done); 1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for going to the next element by incrementing the 1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // index (smi) stored on top of the stack. 1076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.continue_target()); 1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); 1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Slow case for the stack limit check. 1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StackCheckStub stack_check_stub; 1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_limit_hit); 1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stack_check_stub); 1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&stack_check_done); 1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.break_target()); 1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ addq(rsp, Immediate(5 * kPointerSize)); 1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) { 1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // space for nested functions that don't need literals cloning. 1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && info->num_literals() == 0) { 1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastNewClosureStub stub; 1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(info); 1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rsi); 1105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(info); 1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kNewClosure, 2); 1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 1114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->var(), context_); 1115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var, 1119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Four cases: non-this global variables, lookup slots, all other 1121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // types of slots, and parameters that rewrite to explicit property 1122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // accesses on the arguments object. 1123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Slot* slot = var->slot(); 1124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Property* property = var->AsProperty(); 1125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1126d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (var->is_global() && !var->is_this()) { 11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "Global variable"); 11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use inline caching. Variable name is passed in rcx and the global 11293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // object on the stack. 1130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, var->name()); 11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ movq(rax, CodeGenerator::GlobalObject()); 11323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 11333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 11343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // A test rax instruction following the call is used by the IC to 11353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // indicate that the inobject property case was inlined. Ensure there 11363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is no test rax instruction here. 1137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context, rax); 1139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Lookup slot"); 1142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rsi); // Context. 1143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ Push(var->name()); 1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 1145d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context, rax); 1146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1147d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL) { 1148d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1149d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ? "Context slot" 1150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : "Stack slot"); 1151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (var->mode() == Variable::CONST) { 1152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Constants may be the hole value if they have not been initialized. 1153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Unhole them. 1154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 1155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke MemOperand slot_operand = EmitSlotSearch(slot, rax); 1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, slot_operand); 1157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 1161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, rax); 1162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, slot); 1164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1165d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1167d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Rewritten parameter"); 1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(property); 1169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Rewritten parameter accesses are of the form "slot[literal]". 1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the object is in a slot. 1172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 1173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NOT_NULL(object_var); 1174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Slot* object_slot = object_var->slot(); 1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_slot); 1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the object. 1178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand object_loc = EmitSlotSearch(object_slot, rax); 11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ movq(rdx, object_loc); 1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the key is a smi. 1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key_literal = property->key()->AsLiteral(); 1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(key_literal); 1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(key_literal->handle()->IsSmi()); 1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the key. 11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(rax, key_literal->handle()); 1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a keyed property load. 1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Notice: We must not have a "test rax, ..." instruction after the 1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // call. It is treated specially by the LoadIC code. 1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context, rax); 11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 1202bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label materialized; 12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rdi = JS function. 1205bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rcx = literals array. 1206bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rbx = regexp literal. 1207bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rax = regexp literal clone. 12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1209bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1212bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rbx, FieldOperand(rcx, literal_offset)); 1213bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 1214bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &materialized); 1215bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create regexp literal using runtime function 12173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Result will be in rax. 1218bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(rcx); 12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->pattern()); 12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->flags()); 12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1223bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rbx, rax); 1224bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1225bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&materialized); 1226bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1227bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label allocated, runtime_allocate; 1228bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 1229bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&allocated); 1230bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1231bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&runtime_allocate); 1232bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(rbx); 1233bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Push(Smi::FromInt(size)); 1234bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1235bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(rbx); 1236bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1237bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&allocated); 1238bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Copy the content into the newly allocated memory. 1239bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // (Unroll copy loop once for better throughput). 1240bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 1241bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rdx, FieldOperand(rbx, i)); 1242bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); 1243bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, i), rdx); 1244bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, i + kPointerSize), rcx); 1245bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1246bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if ((size % (2 * kPointerSize)) != 0) { 1247bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); 1248bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(FieldOperand(rax, size - kPointerSize), rdx); 1249bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(Smi::FromInt(expr->literal_index())); 1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(expr->constant_properties()); 12606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(Smi::FromInt(expr->fast_elements() ? 1 : 0)); 1261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->depth() > 1) { 12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4); 1265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in rax. 1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Save result on the stack 1279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::CONSTANT: 1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 1284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kAccumulator); 1290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, key->handle()); 12914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 1292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 1299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 1300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 1301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 1302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kSetProperty, 3); 1303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::SETTER: 1305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::GETTER: 1306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, 0)); // Duplicate receiver. 1307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 1308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(property->kind() == ObjectLiteral::Property::SETTER ? 1309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(1) : 1310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(0)); 1311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 1312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDefineAccessor, 4); 1313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1325d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 1330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 13333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 1334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(expr->constant_elements()); 13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (expr->depth() > 1) { 1336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (length > FastCloneShallowArrayStub::kMaximumLength) { 1338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastCloneShallowArrayStub stub(length); 1341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 13423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 13453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 13523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 13553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 13583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(rax); 13593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 13603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(subexpr, kAccumulator); 13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Store the subexpression value in the array's elements. 13643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 13653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 13663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(FieldOperand(rbx, offset), result_register()); 13683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Update the write barrier for the array store. 1370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(rbx, offset, result_register(), rcx); 13713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 1391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 1394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Property* prop = expr->target()->AsProperty(); 1395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (prop != NULL) { 1396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu assign_type = 1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 1408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kAccumulator); 1409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 1412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->is_compound()) { 1416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 1417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kAccumulator); 1418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 0)); 1419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 1420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 1422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kStack); 1423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1424402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1425402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Get value of LHS expression and 1428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // store in on top of the stack. 1429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kStack; 1432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableLoad(expr->target()->AsVariableProxy()->var(), 1435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression::kValue); 1436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyLoad(prop); 1439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyLoad(prop); 1443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate RHS expression. 1450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression* rhs = expr->value(); 1451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(rhs, kAccumulator); 1452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Apply operator. 1454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kAccumulator; 1457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitBinaryOp(expr->binary_op(), Expression::kValue); 1458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke expr->op(), 1469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu context_); 1470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, key->handle()); 1485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 1500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(op, 1503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 1504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_GENERIC_BINARY_FLAGS); 1505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 1506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, rax); 1507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 1519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 1532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); 1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Preserve value. 1537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kAccumulator); 1538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 1539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rax); // Restore value. 1540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rcx, prop->key()->AsLiteral()->handle()); 1541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ nop(); // Signal no inlined code. 1544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Preserve value. 1548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 15498defd9ff6930b4e24729971a61cf7469daf119beSteve Block VisitForValue(prop->key(), kAccumulator); 15508defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ movq(rcx, rax); 15518defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ pop(rdx); 15528defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ pop(rax); 1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ nop(); // Signal no inlined code. 1556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::Value op, 1564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand sides that rewrite to explicit property accesses do not reach 1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // here. 15673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var->is_global() || var->slot() != NULL); 1569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 15703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1571d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in rax, variable name in 1574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rcx, and the global object on the stack. 15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Move(rcx, var->name()); 15764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, CodeGenerator::GlobalObject()); 15773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 15783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ nop(); 1580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 1582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment for non-const variables and for initialization 1583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // of const variables. Const assignments are simply skipped. 1584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 1585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Slot* slot = var->slot(); 1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Slot::LOCAL: 1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rbp, SlotOffset(slot))); 1592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment. 1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(Operand(rbp, SlotOffset(slot)), rax); 1597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, rcx); 1601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, target); 1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment and issue the write barrier. 1608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(target, rax); 1609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The value of the assignment is in rax. RecordWrite clobbers its 1610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // register arguments. 1611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(rcx, offset, rdx, rbx); 1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call the runtime for the assignment. The runtime will ignore 1619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // const reinitialization. 1620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Value. 1621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rsi); // Context. 1622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 1623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime will ignore const redeclaration. 1625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 16303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 16323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, rax); 16353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 16433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(rsp, kPointerSize)); // Receiver is now under value. 1650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, prop->key()->AsLiteral()->handle()); 16574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (expr->ends_initialization_block()) { 16584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ movq(rdx, Operand(rsp, 0)); 16594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 16604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 16614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 16724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke DropAndApply(1, context_, rax); 16734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 16744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1679d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(rsp, 2 * kPointerSize)); 1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rcx); 1694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->ends_initialization_block()) { 1695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. 1696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 1698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This nop signals to the IC that there is no inlined code at the call 1704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // site for it to patch. 1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 1710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); // Result of assignment, saved even if not needed. 1711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rdx); 1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 17257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(expr->obj(), kAccumulator); 1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 17277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, rax); 1728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(expr->obj(), kStack); 17307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(expr->key(), kAccumulator); 17317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(rdx); 1732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 17337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, rax); 1734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1738d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 1739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Object> name, 1740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 1741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 1742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 17433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 17443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 1745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 17463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Move(rcx, name); 1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 17493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SetSourcePosition(expr->position()); 17503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 1751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 17523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke in_loop); 1754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, mode); 1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1757402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, rax); 1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 17619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 17629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Expression* key, 17639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen RelocInfo::Mode mode) { 17649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Code common for calls using the IC. 17659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ZoneList<Expression*>* args = expr->arguments(); 17669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int arg_count = args->length(); 17679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0; i < arg_count; i++) { 17689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen VisitForValue(args->at(i), kStack); 17699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 17709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen VisitForValue(key, kAccumulator); 17719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ movq(rcx, rax); 17729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source position for debugger. 17739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen SetSourcePosition(expr->position()); 17749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call the IC initialization code. 17759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 17769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, 17779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen in_loop); 17789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ Call(ic, mode); 17799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Restore context register. 17809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 17819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Apply(context_, rax); 17829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 17839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 17849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1785d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 1786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 1787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 1793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 17993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Discard the function left on TOS. 1800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 1801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // resolve the function we need to call and the receiver of the 1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. The we call the resolved function using the given 1813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(fun, kStack); 1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. 1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the arguments. 1818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 1819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 1820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 1821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(i), kStack); 1822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the function - found below the arguments. 1825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); 1826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the first argument or undefined if it doesn't exist. 1828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (arg_count > 0) { 1829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(rsp, arg_count * kPointerSize)); 1830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the receiver of the enclosing function and do runtime call. 1835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); 1836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 1837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime call returns a pair of values in rax (function) and 1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rdx (receiver). Touch up the stack with the right values. 1840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 1841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 1842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 1844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetSourcePosition(expr->position()); 1845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 1849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke DropAndApply(1, context_, rax); 1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 1852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a global variable. 1853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object as receiver for the call IC lookup. 1854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && var->slot() != NULL && 1857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block var->slot()->type() == Slot::LOOKUP) { 1858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call to a lookup slot (dynamically introduced variable). Call 1859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the runtime to find the function to call (returned in rax) and 1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the object holding it (returned in rdx). 1861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 1862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 1863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); // Function. 1865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rdx); // Receiver. 1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitCallWithStub(expr); 1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 1868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 1870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 1871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 1872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 1873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 18769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call to a keyed property. 18779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // For a synthetic property use keyed load IC followed by function call, 18789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // for a regular property use KeyedCallIC. 1879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (prop->is_synthetic()) { 18819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen VisitForValue(prop->key(), kAccumulator); 18829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ movq(rdx, Operand(rsp, 0)); 18839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source code position for IC call. 18849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen SetSourcePosition(prop->position()); 18859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 18869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ call(ic, RelocInfo::CODE_TARGET); 18879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // By emitting a nop we make sure that we do not have a "test rax,..." 18889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // instruction after the call as it is treated specially 18899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // by the LoadIC code. 18909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ nop(); 18919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Pop receiver. 18929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ pop(rbx); 18939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Push result (function). 18949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ push(rax); 18959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Push receiver object on stack. 1896e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rcx, CodeGenerator::GlobalObject()); 1897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 18989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen EmitCallWithStub(expr); 1899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 19009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 19033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // also use the fast code generator. 1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 1908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 1911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(fun, kStack); 1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 1915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rbx, CodeGenerator::GlobalObject()); 1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1923d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push function on the stack. 1929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 1930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object (receiver). 1932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 19393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load function, arg_count into rdi and rax. 1946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(rax, arg_count); 1947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Function is in rsp[arg_count + 1]. 1948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); 1949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Replace function on TOS with result in rax, or pop it. 1954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, rax); 19553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 19563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 19573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_true); 1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Condition positive_smi = __ CheckPositiveSmi(rax); 1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(positive_smi, if_true); 1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kNullValueRootIndex); 2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_false); 2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); 2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, if_false); 2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); 2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below_equal, if_true); 2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 20233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(args->length() == 1); 20243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch VisitForValue(args->at(0), kAccumulator); 20263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 20283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 20293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 20303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 20313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ JumpIfSmi(rax, if_false); 20333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 20343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ j(above_equal, if_true); 20353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ jmp(if_false); 20363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Apply(context_, if_true, if_false); 20383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 20393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_true); 2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), 2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &check_frame_marker); 2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), 2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Smi::FromInt(StackFrame::CONSTRUCT)); 2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); 2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rbx); 2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(rax, rbx); 2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ArgumentsAccessStub expects the key in edx and the formal 2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // parameter count in eax. 2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label exit; 2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset), 2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &exit); 2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (FLAG_debug_code) __ AbortIfNotSmi(rax); 2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &null); 2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); // Map is now in rax. 2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, &null); 2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // As long as JS_FUNCTION_TYPE is the last instance type and it is 2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // LAST_JS_OBJECT_TYPE. 2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpInstanceType(rax, JS_FUNCTION_TYPE); 2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &function); 2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the constructor in the map is a function. 2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, Map::kConstructorOffset)); 2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &non_function_constructor); 2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rax now contains the constructor function. Grab the 2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); 2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); 2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rax, Factory::function_class_symbol()); 2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Move(rax, Factory::Object_symbol()); 2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kNullValueRootIndex); 2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING 2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif 2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber); 2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 22933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Allocate a heap number. 22943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rbx, rax); 2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Return a random uint32 number in rax. 2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. 2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(0); 2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction(ExternalReference::random_uint32_function(), 0); 2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in rax to 0.(32 random bits) in a double 2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm1, rcx); 2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm0, rax); 2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cvtss2sd(xmm1, xmm1); 2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ xorpd(xmm0, xmm1); 2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ subsd(xmm0, xmm1); 2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0); 2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, rbx); 2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(3), kStack); 2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); // Load the object. 2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &done); 2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); 2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(rax, JSValue::kValueOffset)); 2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_pow, 2); 2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); // Load the object. 2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); // Load the value. 2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rbx); // rax = value. ebx = object. 2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rbx, &done); 2383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 2385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); 2386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax); 2390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rdx, rax); 2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx); 2394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(rax, rbx); 24197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 24207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 2421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 24237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 24267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, rbx); 24277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 24287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 24317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 24327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(0), kStack); 24347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(1), kAccumulator); 24357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 24377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 24387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = rcx; 24397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rdx; 24407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 24427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 24447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 24457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 24477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 24487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch, 24497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 24507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 24537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 24547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 24587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 24597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 24607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 24617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 24647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move the undefined value into the result register, which will 24657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 24667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 24677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 24707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 24737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, result); 2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 24787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 24797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(0), kStack); 24817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(1), kAccumulator); 24827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 24847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 24857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = rcx; 24867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = rdx; 24877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rax; 24887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 24907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 24927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 24937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 24957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 24967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 24977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 24987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 24997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 25007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 25017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 25027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 25037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 25047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 25077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 25087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 25097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kEmptyStringRootIndex); 25107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 25137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 25147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 25157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(result, Smi::FromInt(0)); 25167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 25197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 25207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 25227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, result); 2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke TranscendentalCacheStub stub(TranscendentalCache::SIN); 2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke TranscendentalCacheStub stub(TranscendentalCache::COS); 2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime function. 2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sqrt, 1); 2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length() - 2; // For receiver and function. 2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); // Receiver. 2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(i + 1), kStack); 2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(arg_count + 1), kAccumulator); // Function. 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // InvokeFunction requires function in rdi. Move it in there. 2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!result_register().is(rdi)) __ movq(rdi, result_register()); 2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeFunction(rdi, count, CALL_FUNCTION); 2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kRegExpConstructResult, 3); 2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kSwapElements, 3); 2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Top::global_context()->jsfunction_result_caches()); 2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); 2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = rax; 2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = rbx; 2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register tmp = rcx; 2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, CodeGenerator::ContextOperand(rsi, Context::GLOBAL_INDEX)); 2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, GlobalObject::kGlobalContextOffset)); 2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CodeGenerator::ContextOperand( 2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(cache, 2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, not_found; 2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SmiIndex index = 2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2); 2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(key, FieldOperand(cache, 2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 2655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize)); 2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, ¬_found); 2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(rax, FieldOperand(cache, 2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize + kPointerSize)); 2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(cache); 2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(key); 2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2675bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 2676bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT_EQ(2, args->length()); 2677bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2678bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register right = rax; 2679bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register left = rbx; 2680bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp = rcx; 2681bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2682bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch VisitForValue(args->at(0), kStack); 2683bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch VisitForValue(args->at(1), kAccumulator); 2684bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(left); 2685bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2686bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label done, fail, ok; 2687bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(left, right); 2688bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(equal, &ok); 2689bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Fail if either is a non-HeapObject. 2690bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Condition either_smi = masm()->CheckEitherSmi(left, right, tmp); 2691bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(either_smi, &fail); 2692bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(zero, &fail); 2693bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset)); 2694bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset), 2695bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Immediate(JS_REGEXP_TYPE)); 2696bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &fail); 2697bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset)); 2698bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &fail); 2699bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset)); 2700bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset)); 2701bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(equal, &ok); 2702bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&fail); 2703bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Move(rax, Factory::false_value()); 2704bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&done); 2705bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&ok); 2706bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Move(rax, Factory::true_value()); 2707bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&done); 2708bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2709bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Apply(context_, rax); 2710bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2711bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2712bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2713d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 27223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 27233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 2726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rax, CodeGenerator::GlobalObject()); 2727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 2728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 27293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 27303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 27313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 27323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 2733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 2734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Call the JS runtime function using a call IC. 2738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Move(rcx, expr->name()); 2739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 2741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 2742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 2746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, rax); 2748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2751d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->expression()->AsProperty(); 2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop == NULL && var == NULL) { 2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-property, non-variable reference is true. 2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression may have side effects. 2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, true); 2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var != NULL && 2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke !var->is_global() && 2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke var->slot() != NULL && 2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke var->slot()->type() != Slot::LOOKUP) { 2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-global, non-dynamic variables is false. 2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression does not have side effects. 2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, false); 2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Property or variable reference. Call the delete builtin with 2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object and property name as arguments. 2772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 2774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kStack); 2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->is_global()) { 2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(CodeGenerator::GlobalObject()); 2777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 2778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-global variable. Call the runtime to look up the context 2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // where the variable was introduced. 2781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 2782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 2783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLookupContext, 2); 2784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(rax); 2785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(var->name()); 2786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 2788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 2789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2795e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 2796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 2797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 2801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 2803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 2804e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 2805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 2806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 2808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 2809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 2813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Value is false so it's needed. 2814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 2815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 2816e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 2817e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 2819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ PushRoot(Heap::kUndefinedValueRootIndex); 2820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through. 2823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 2824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 2825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 2826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 2832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Notice that the labels are swapped. 2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); 2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForControl(expr->expression(), if_true, if_false); 2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_false, if_true); // Labels swapped. 2843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 2847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (proxy != NULL && 2850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block !proxy->var()->is_this() && 2851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->is_global()) { 2852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "Global variable"); 2853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Move(rcx, proxy->name()); 28547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ movq(rax, CodeGenerator::GlobalObject()); 2855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 2856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Use a regular load, not a contextual load, to avoid a reference 2857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // error. 2858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 28597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(rax); 2860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (proxy != NULL && 2861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot() != NULL && 2862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot()->type() == Slot::LOOKUP) { 2863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rsi); 2864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Push(proxy->name()); 2865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(rax); 2867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This expression cannot throw a reference error at the top level. 2869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 2870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 2874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2877d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 2878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 2879d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke VisitForValue(expr->expression(), kAccumulator); 2880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 28814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 2882d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &no_conversion); 2883d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(result_register()); 2884d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 2885d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 2886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context_, result_register()); 2887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 2888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 28904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 28914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 2892ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke bool can_overwrite = 28934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 28944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 2895ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke UnaryOverwriteMode overwrite = 2896ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 28974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::SUB, overwrite); 28984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 28994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register rax. 29004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 29014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 29024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 29034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 29044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 29054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 29064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 29074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 2908ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke bool can_overwrite = 29094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 29104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 2911ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke UnaryOverwriteMode overwrite = 2912ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 29134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); 29144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 29154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register rax. 29164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 29174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Avoid calling the stub for Smis. 29184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Label smi, done; 29194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Condition is_smi = masm_->CheckSmi(result_register()); 29204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ j(is_smi, &smi); 29214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Non-smi: call stub leaving result in accumulator register. 29224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 29234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ jmp(&done); 29244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Perform operation directly on Smis. 29254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&smi); 29264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ SmiNot(result_register(), result_register()); 29274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 29284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, result_register()); 29294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 29304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 29314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 29343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 29353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 29363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 29373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2938d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Comment cmnt(masm_, "[ CountOperation"); 2940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand-sides are rewritten to have a 'throw 2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' as the left-hand side. 2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 2949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 2950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 2952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 2953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 2954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 2955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 2956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 2957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 2958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 2961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 2962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 2963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Location saved_location = location_; 2964d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke location_ = kAccumulator; 2965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 2966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kValue); 2967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke location_ = saved_location; 2968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2969e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 2970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix() && context_ != Expression::kEffect) { 2971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Smi::FromInt(0)); 2972e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 29747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(prop->obj(), kAccumulator); 29757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(rax); // Copy of receiver, needed for later store. 2976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 2977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 29787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(prop->obj(), kStack); 29797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(prop->key(), kAccumulator); 29807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 29817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(rax); // Copy of key, needed for later store. 2982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2986d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 2987d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 2988d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Condition is_smi; 2989d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke is_smi = masm_->CheckSmi(rax); 2990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &no_conversion); 2991d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(rax); 2992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 2993d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 2994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 2996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2997e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 2998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 2999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 3000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 3001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do not save result. 3002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3003e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 3004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 3005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 3007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the result on the stack. If we have a named or keyed property 3008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // we store the result under the receiver that is currently on top 3009e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the stack. 3010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 3011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 3012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(rax); 3013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: 3015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, kPointerSize), rax); 3016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: 3018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 2 * kPointerSize), rax); 3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3020e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3025d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 3026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 3027d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (loop_depth() > 0) { 3028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 3029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 3030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 3031d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 3032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(overflow, &stub_call); 3034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 3035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 3036d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke is_smi = masm_->CheckSmi(rax); 3037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(is_smi, &done); 3038d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 3039d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 3040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 3041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiSubConstant(rax, rax, Smi::FromInt(1)); 3042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 3043d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ SmiAddConstant(rax, rax, Smi::FromInt(1)); 3044d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3045d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 3047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(expr->binary_op(), 3048e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 3049e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_GENERIC_BINARY_FLAGS); 30504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke stub.GenerateCall(masm_, rax, Smi::FromInt(1)); 3051d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 3052e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in rax. 3054e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 3055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 3056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 3057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 3058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::ASSIGN, 3060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kEffect); 3061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 3062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 3063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 3064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 3065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 3068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::ASSIGN, 3070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke context_); 3071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 3074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, prop->key()->AsLiteral()->handle()); 30754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(rdx); 3076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 3078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // This nop signals to the IC that there is no inlined code at the call 3079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // site for it to patch. 3080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 3081e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 3082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 3083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 3084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3085e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 30864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, rax); 3087e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3088e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3089e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3090e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rcx); 3092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(rdx); 3093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3094e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 3095e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // This nop signals to the IC that there is no inlined code at the call 3096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // site for it to patch. 3097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 3098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 3099e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 3100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 3101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, rax); 3104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 3106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3110d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 3111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ BinaryOperation"); 3112d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3113d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::COMMA: 3114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->left()); 3115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Visit(expr->right()); 3116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::OR: 3119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::AND: 3120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitLogicalOperation(expr); 3121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::ADD: 3124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SUB: 3125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::DIV: 3126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MOD: 3127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MUL: 3128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_OR: 3129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_AND: 3130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_XOR: 3131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHL: 3132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHR: 3133e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::SAR: 3134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 3135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 3136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitBinaryOp(expr->op(), context_); 3137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 31413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 31433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 31443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNullCompare(bool strict, 3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register obj, 3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register null_const, 3148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true, 3149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false, 3150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register scratch) { 3151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmpq(obj, null_const); 3152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (strict) { 3153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 3154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 3155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 3156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(obj, Heap::kUndefinedValueRootIndex); 3157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 3158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(obj, if_false); 3159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // It can be an undetectable object. 3160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset)); 3161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(scratch, Map::kBitFieldOffset), 3162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 3163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_true); 3164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 3166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 3171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 3173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 3174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 3177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 3178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 3180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 3182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 3183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CompareRoot(rax, Heap::kTrueValueRootIndex); 3185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 3186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 31883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 3190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 3191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 3192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 3194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, if_true); // The stub returns 0 for true. 3195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 3200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 3201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = no_condition; 3202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 3203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 3205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 3206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 3207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::EQ: { 3208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = equal; 3209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 3210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If either operand is constant null we do a fast compare 3211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // against null. 3212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Literal* right_literal = expr->right()->AsLiteral(); 3213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Literal* left_literal = expr->left()->AsLiteral(); 3214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (right_literal != NULL && right_literal->handle()->IsNull()) { 3215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitNullCompare(strict, rdx, rax, if_true, if_false, rcx); 3216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 3217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (left_literal != NULL && left_literal->handle()->IsNull()) { 3219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitNullCompare(strict, rax, rdx, if_true, if_false, rcx); 3220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 3221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 3226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 3227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 3228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 3230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 3231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 3232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 3233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 3234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 3236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 3237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 3238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, result_register()); 3239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rax); 3240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 3242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 3243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(rdx); 3244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 3246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 3247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 3249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The comparison stub expects the smi vs. smi case to be handled 3252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // before it is called. 3253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label slow_case; 3254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ JumpIfNotBothSmi(rax, rdx, &slow_case); 3255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ SmiCompare(rdx, rax); 3256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(cc, if_true); 3257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&slow_case); 3260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CompareStub stub(cc, strict); 3261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ testq(rax, rax); 3263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(cc, if_true); 3264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 32663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 32673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 3269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 3270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_true, if_false); 3271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3274d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 3275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 3276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, rax); 3277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3280d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return rax; } 3281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3283d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return rsi; } 3284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3286d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(IsAligned(frame_offset, kPointerSize)); 3288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rbp, frame_offset), value); 32893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 32903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 32913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3292d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index)); 3294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 3298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 3299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3301d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 3302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 3303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 3304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address on top of stack (smi encoded Code* delta) 3305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, Operand(rsp, 0)); 3306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 3307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subq(rdx, rcx); 3308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Integer32ToSmi(rdx, rdx); 3309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), rdx); 3310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 3311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 3312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 3316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rdx)); 3317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(rcx)); 3318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 3319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 3320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address. 3321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rdx, Operand(rsp, 0)); 3322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiToInteger32(rdx, rdx); 3323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 3324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ addq(rdx, rcx); 3325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(Operand(rsp, 0), rdx); 3326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // And return. 3327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 3328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __ 3332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 33343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 3335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 3337