full-codegen-ia32.cc revision 7f4d5bd8c03935e2c0cd412e561b8fc5a6a880ae
1f7060e27768c550ace7ec48ad8c093466db52dfaLeon 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_IA32) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h" 33d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h" 34e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#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 edi: the JS function object being called (ie, ourselves) 513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o esi: our context 523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o ebp: our caller's frame pointer 533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o esp: stack pointer (pointing to return address) 543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-ia32.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(ebp); // Caller's frame pointer. 654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(ebp, esp); 664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(esi); // Callee's context. 674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edi); // 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 __ push(Immediate(Factory::undefined_value())); 734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else if (locals_count > 1) { 744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(eax, Immediate(Factory::undefined_value())); 754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < locals_count; i++) { 764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(eax); 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 edi. 884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edi); 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 eax and esi. It replaces the context 974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // passed to us. It's saved in the stack and kept live in esi. 984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Copy parameters into context if necessary. 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 __ mov(eax, Operand(ebp, parameter_offset)); 1094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Store it in the context. 1104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int context_offset = Context::SlotOffset(slot->index()); 1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(Operand(esi, context_offset), eax); 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 esi. 1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(ecx, esi); 1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(ecx, context_offset, eax, ebx); 1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Variable* arguments = scope()->arguments()->AsVariable(); 1224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (arguments != NULL) { 1234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Function uses arguments object. 1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate arguments object"); 1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (function_in_register) { 1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edi); 1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Receiver is just before the parameters on the caller's stack. 1313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int offset = scope()->num_parameters() * kPointerSize; 1323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ lea(edx, 1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); 1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); 1353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ push(Immediate(Smi::FromInt(scope()->num_parameters()))); 1364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Arguments to ArgumentsAccessStub: 1374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // function, receiver address, parameter count. 1384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The stub will rewrite receiver and parameter count if the previous 1394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // stack frame was an arguments adapter frame. 1404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 1414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 1424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(ecx, eax); // Duplicate result. 1434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(arguments->slot(), eax, ebx, edx); 1444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Slot* dot_arguments_slot = 1453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->arguments_shadow()->AsVariable()->slot(); 1464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(dot_arguments_slot, ecx, ebx, edx); 147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block { Comment cmnt(masm_, "[ Declarations"); 151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // For named function expressions, declare the function name as a 152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant. 153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && scope()->function() != NULL) { 154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(scope()->function(), Variable::CONST, NULL); 155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Visit all the explicit declarations unless there is an illegal 157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // redeclaration. 158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->HasIllegalRedeclaration()) { 159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke scope()->VisitIllegalRedeclaration(this); 160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitDeclarations(scope()->declarations()); 162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Stack check"); 1663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label ok; 167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::address_of_stack_limit(); 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(esp, Operand::StaticVariable(stack_limit)); 1703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &ok, taken); 1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block StackCheckStub stub; 1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallStub(&stub); 1733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&ok); 1743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceEnter, 0); 1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Body"); 181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu VisitStatements(function()->body()); 183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit a 'return undefined' in case control fell off the end of the body. 1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, Factory::undefined_value()); 1897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Common return label 200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(eax); 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 2107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position()); 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 __ mov(esp, ebp); 2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(ebp); 2163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ ret((scope()->num_parameters() + 1) * kPointerSize); 217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check that the size of the code used for returning matches what is 219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expected by the debugger. 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(Assembler::kJSReturnSequenceLength, 221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 227d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) { 228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Move value into place. 238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ mov(result_register(), reg); 241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(reg); 244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For simplicity we always test the accumulator register. 250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ mov(result_register(), reg); 251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ mov(result_register(), reg); 257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 270d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { 271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand slot_operand = EmitSlotSearch(slot, result_register()); 279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), slot_operand); 282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Memory operands can be pushed directly. 285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(slot_operand); 286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For simplicity we always test the accumulator register. 293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { 314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), lit->handle()); 324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Immediates can be pushed directly. 327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(lit->handle())); 328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For simplicity we always test the accumulator register. 334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), lit->handle()); 335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), lit->handle()); 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) { 355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For simplicity we always test the accumulator register. 375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Operand(esp, 0)); 387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count, 396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context, 397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register reg) { 398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!reg.is(esp)); 400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ mov(result_register(), reg); 413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(esp, 0), reg); 417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For simplicity we always test the accumulator register. 423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ mov(result_register(), reg); 425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ mov(result_register(), reg); 434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), reg); 438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(esp, 0), result_register()); 439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::PrepareTest(Label* materialize_true, 448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* materialize_false, 449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label** if_true, 450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label** if_false) { 451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (context_) { 452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kUninitialized: 453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke UNREACHABLE(); 454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kEffect: 456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In an effect context, the true and the false case branch to the 457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // same label. 458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = *if_false = materialize_true; 459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValue: 461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = materialize_true; 462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = materialize_false; 463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTest: 465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = true_label_; 466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = false_label_; 467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValueTest: 469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = materialize_true; 470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = false_label_; 471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTestValue: 473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = true_label_; 474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = materialize_false; 475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 480d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, 481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_true, 482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_false) { 483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(materialize_true, materialize_false); 488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Factory::true_value()); 497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&done); 498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Factory::false_value()); 500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(Factory::true_value())); 504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&done); 505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(Factory::false_value())); 507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Factory::true_value()); 521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(Factory::true_value())); 524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Factory::false_value()); 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(Factory::false_value())); 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Convert constant control flow (true or false) to the result expected for 546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// a given expression context. 547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, bool flag) { 548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (context) { 549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kUninitialized: 550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke UNREACHABLE(); 551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kEffect: 553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValue: { 555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Object> value = 556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke flag ? Factory::true_value() : Factory::false_value(); 557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(result_register(), value); 560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(value)); 563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTest: 568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(flag ? true_label_ : false_label_); 569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTestValue: 571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is false it's needed. 574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!flag) __ mov(result_register(), Factory::false_value()); 575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is false it's needed. 578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!flag) __ push(Immediate(Factory::false_value())); 579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(flag ? true_label_ : false_label_); 582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValueTest: 584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is true it's needed. 587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (flag) __ mov(result_register(), Factory::true_value()); 588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is true it's needed. 591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (flag) __ push(Immediate(Factory::true_value())); 592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(flag ? true_label_ : false_label_); 595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) { 601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The value to test is in the accumulator. If the value might be needed 602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // on the stack (value/test and test/value contexts with a stack location 603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // desired), then the value is already duplicated on the stack. 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, true_label_); 605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, false_label_); 606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In value/test and test/value expression contexts with stack as the 608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // desired location, there is already an extra value on the stack. Use a 609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // label to discard it if unneeded. 610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label discard; 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_true = true_label_; 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* if_false = false_label_; 613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_false = &discard; 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if_true = &discard; 635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the inlined tests assumed by the stub. 641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(result_register(), Factory::undefined_value()); 642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(result_register(), Factory::true_value()); 644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(result_register(), Factory::false_value()); 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(result_register(), Operand(result_register())); 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, if_false); 650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(result_register(), Immediate(kSmiTagMask)); 651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, if_true); 652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save a copy of the value if it may be needed and isn't already saved. 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the ToBoolean stub for all other cases. 682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ToBooleanStub stub; 683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(eax, Operand(eax)); 686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The stub returns nonzero for true. Complete based on the context. 688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, true_label_); 696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, &discard); 703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, true_label_); 708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, &discard); 719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, false_label_); 724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(true_label_); 729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 734d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (slot->type()) { 736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOCAL: 738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(ebp, SlotOffset(slot)); 739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::CONTEXT: { 740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int context_chain_length = 7413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->ContextChainLength(slot->var()->scope()); 742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadContext(scratch, context_chain_length); 743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CodeGenerator::ContextOperand(scratch, slot->index()); 744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOOKUP: 746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(eax, 0); 750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 753d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) { 754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(source, destination); 755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(destination, location); 756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 759d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst, 760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register src, 761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2) { 763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!scratch1.is(src) && !scratch2.is(src)); 765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(dst, scratch1); 766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(location, src); 767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (dst->type() == Slot::CONTEXT) { 769e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(scratch1, offset, src, scratch2); 771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable, 776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable::Mode mode, 777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FunctionLiteral* function) { 778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(variable != NULL); // Must have been resolved. 780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Slot* slot = variable->slot(); 781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = variable->AsProperty(); 782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(ebp, SlotOffset(slot)), 788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(Factory::the_hole_value())); 789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(ebp, SlotOffset(slot)), result_register()); 792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ebx, 804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); 805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(ebx, Operand(esi)); 806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(equal, "Unexpected declaration in current context."); 807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(CodeGenerator::ContextOperand(esi, slot->index()), 810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(Factory::the_hole_value())); 811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the hole value is in old space. 812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(CodeGenerator::ContextOperand(esi, slot->index()), 815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result_register()); 816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 8174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(ebx, esi); 8184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(ebx, offset, result_register(), ecx); 819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(esi); 824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(variable->name())); 825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(mode == Variable::VAR || mode == Variable::CONST); 827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; 828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(Smi::FromInt(attr))); 829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(Factory::the_hole_value())); 835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kStack); 837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(Smi::FromInt(0))); // No initial value! 839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL || mode == Variable::CONST) { 847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL) { 8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block VisitForValue(prop->key(), kStack); 852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block VisitForValue(prop->key(), kAccumulator); 8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, result_register()); 857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Factory::the_hole_value()); 858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 8596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Absence of a test eax instruction following the call 864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // indicates that none of the load was inlined. 865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 876d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(esi); // The context is the first argument. 8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(pairs)); 8803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(stmt->tag(), kStack); 892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(clause->label(), kAccumulator); 912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the comparison as if via '==='. The comparison stub expects 914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the smi vs. smi case to be handled before it is called. 915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_case; 916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, Operand(esp, 0)); // Switch value. 917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, edx); 918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ or_(ecx, Operand(eax)); 919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(ecx, Immediate(kSmiTagMask)); 920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, &slow_case, not_taken); 921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(edx, Operand(eax)); 922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(clause->body_target()->entry_label()); 925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_case); 927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CompareStub stub(equal, true); 928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Operand(eax)); 930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(clause->body_target()->entry_label()); 933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(nested_statement.break_target()); 941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(default_clause->body_target()->entry_label()); 943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(clause->body_target()->entry_label()); 950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(nested_statement.break_target()); 954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the object to enumerate over. Both SpiderMonkey and JSC 966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ignore null and undefined in contrast to the specification; see 967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ECMA-262 section 12.6.4. 968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(stmt->enumerable(), kAccumulator); 969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::undefined_value()); 970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::null_value()); 972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, &convert); 978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, &done_convert); 980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); 982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); 9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 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(eax); // 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 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map()); 1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &fixed_array); 1002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register eax. Get the enumeration cache from it. 1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); 1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); 1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Setup the four remaining stack slots. 1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Map. 1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(edx); // Enumeration cache. 1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); 1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Enumeration cache length (as smi). 1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Smi::FromInt(0))); // Initial index. 1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register eax. Iterate through that. 1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check. 1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); 1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 1021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Fixed array length (as smi). 1022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Smi::FromInt(0))); // Initial index. 1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 1025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. 1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. 1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, loop_statement.break_target()); 1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register ebx. 1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, Operand(esp, 2 * kPointerSize)); 1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); 1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the expected map from the stack or a zero map in the 1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register edx. 1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, Operand(esp, 3 * kPointerSize)); 1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If not, we have to filter the key. 1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label update_each; 1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, Operand(esp, 4 * kPointerSize)); 1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &update_each); 1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the entry to a string or null if it isn't a property 1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // anymore. If the property has been removed while iterating, we 1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ecx); // Enumerable. 1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ebx); // Current entry. 1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::null_value()); 1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, loop_statement.continue_target()); 1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, Operand(eax)); 1054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register ebx. 1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(result_register(), ebx); 1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitAssignment(stmt->each()); 1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label stack_limit_hit, stack_check_done; 1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ StackLimitCheck(&stack_limit_hit); 1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_check_done); 1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for going to the next element by incrementing the 1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // index (smi) stored on top of the stack. 1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.continue_target()); 1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); 1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Slow case for the stack limit check. 1076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StackCheckStub stack_check_stub; 1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_limit_hit); 1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stack_check_stub); 1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&stack_check_done); 1080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.break_target()); 1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(Operand(esp), Immediate(5 * kPointerSize)); 1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) { 1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 1093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // space for nested functions that don't need literals cloning. 1094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && info->num_literals() == 0) { 1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastNewClosureStub stub; 1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(info)); 1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(esi); 1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(info)); 1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kNewClosure, 2); 1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, eax); 11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1107d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 1109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->var(), context_); 1110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var, 1114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Four cases: non-this global variables, lookup slots, all other 1116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // types of slots, and parameters that rewrite to explicit property 1117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // accesses on the arguments object. 1118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Slot* slot = var->slot(); 1119d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Property* property = var->AsProperty(); 1120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (var->is_global() && !var->is_this()) { 11223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "Global variable"); 11233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use inline caching. Variable name is passed in ecx and the global 11243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // object on the stack. 1125402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, CodeGenerator::GlobalObject()); 1126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ecx, var->name()); 11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // By emitting a nop we make sure that we do not have a test eax 1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // instruction after the call it is treated specially by the LoadIC code 1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Remember that the assembler may choose to do peephole optimization 1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // (eg, push/pop elimination). 1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 1134402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context, eax); 1135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Lookup slot"); 1138d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(esi); // Context. 1139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(Immediate(var->name())); 1140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 1141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context, eax); 1142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL) { 1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1145d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ? "Context slot" 1146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : "Stack slot"); 1147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (var->mode() == Variable::CONST) { 1148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Constants may be the hole value if they have not been initialized. 1149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Unhole them. 1150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 1151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke MemOperand slot_operand = EmitSlotSearch(slot, eax); 1152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, slot_operand); 1153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::the_hole_value()); 1154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::undefined_value()); 1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 1157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, eax); 1158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, slot); 1160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1161d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1163d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Rewritten parameter"); 1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(property); 1165d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Rewritten parameter accesses are of the form "slot[literal]". 1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the object is in a slot. 1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_var); 1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Slot* object_slot = object_var->slot(); 1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_slot); 1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the object. 1174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand object_loc = EmitSlotSearch(object_slot, eax); 1175402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edx, object_loc); 1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the key is a smi. 1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key_literal = property->key()->AsLiteral(); 1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(key_literal); 1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(key_literal->handle()->IsSmi()); 1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the key. 1183402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, Immediate(key_literal->handle())); 1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a keyed property load. 1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Notice: We must not have a "test eax, ..." instruction after the 1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // call. It is treated specially by the LoadIC code. 1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 1191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Drop key and object left on the stack by IC. 1192402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context, eax); 11933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 11993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 12003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 12013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // edi = JS function. 12023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx = literals array. 12033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax = regexp literal. 12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 12073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, FieldOperand(ebx, literal_offset)); 12093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(eax, Factory::undefined_value()); 12103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &done); 12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create regexp literal using runtime function 12123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Result will be in eax. 12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(ebx); 12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(Smi::FromInt(expr->literal_index()))); 12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(expr->pattern())); 12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(expr->flags())); 12173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 12183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Label done: 12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&done); 1220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, eax); 1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1224d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 1226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); 1228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(expr->constant_properties())); 12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(Immediate(Smi::FromInt(expr->fast_elements() ? 1 : 0))); 1231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->depth() > 1) { 12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4); 1235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in eax. 1239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(eax); // Save result on the stack 1249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 1257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kAccumulator); 1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ecx, Immediate(key->handle())); 12594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(edx, Operand(esp, 0)); 1260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(esp, 0)); // Duplicate receiver. 1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 1269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kSetProperty, 3); 1271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::SETTER: 1273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::GETTER: 1274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(esp, 0)); // Duplicate receiver. 1275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 1276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? 1277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(1) : 1278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(0))); 1279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 1280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDefineAccessor, 4); 1281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UNREACHABLE(); 1283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, eax); 12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1294d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 1299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); 13023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(expr->constant_elements())); 13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (expr->depth() > 1) { 1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (length > FastCloneShallowArrayStub::kMaximumLength) { 1307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastCloneShallowArrayStub stub(length); 1310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(eax); 13283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 13293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(subexpr, kAccumulator); 13313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Store the subexpression value in the array's elements. 13333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ebx, Operand(esp, 0)); // Copy of array literal. 13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(FieldOperand(ebx, offset), result_register()); 13373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Update the write barrier for the array store. 1339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(ebx, offset, result_register(), ecx); 13403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, eax); 13463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Property* prop = expr->target()->AsProperty(); 1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (prop != NULL) { 1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu assign_type = 1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1373402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 1377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kAccumulator); 1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1384402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 1386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->key(), kAccumulator); 1387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edx, Operand(esp, 0)); 1388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 1389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 1391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->key(), kStack); 1392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Get value of LHS expression and 1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // store in on top of the stack. 1398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kStack; 1401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableLoad(expr->target()->AsVariableProxy()->var(), 1404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression::kValue); 1405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyLoad(prop); 1408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyLoad(prop); 1412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1415402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate RHS expression. 1419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression* rhs = expr->value(); 1420402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(rhs, kAccumulator); 1421402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1422402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Apply operator. 1423402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1424402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1425402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kAccumulator; 1426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitBinaryOp(expr->binary_op(), Expression::kValue); 1427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke expr->op(), 1438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu context_); 1439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1450d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ecx, Immediate(key->handle())); 1454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1460d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1468d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 1469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(op, 1472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NO_GENERIC_BINARY_FLAGS, 14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block TypeInfo::Unknown()); 1475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 1476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, eax); 1477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 1489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); 1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Preserve value. 1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kAccumulator); 1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, eax); 1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(eax); // Restore value. 1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, prop->key()->AsLiteral()->handle()); 1511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ nop(); // Signal no inlined code. 1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Preserve value. 1518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 1519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kAccumulator); 1520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, eax); 1521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(edx); 1522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(eax); // Restore value. 1523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ call(ic, RelocInfo::CODE_TARGET); 1525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ nop(); // Signal no inlined code. 1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::Value op, 1534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand sides that rewrite to explicit property accesses do not reach 1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // here. 15373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 15383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var->is_global() || var->slot() != NULL); 1539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 15403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in eax, variable name in 1544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // ecx, and the global object on the stack. 15453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ecx, var->name()); 15464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(edx, CodeGenerator::GlobalObject()); 15473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment for non-const variables and for initialization 1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // of const variables. Const assignments are simply skipped. 1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 1555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Slot* slot = var->slot(); 1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Slot::LOCAL: 1559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, Operand(ebp, SlotOffset(slot))); 1562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(edx, Factory::the_hole_value()); 1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment. 1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(Operand(ebp, SlotOffset(slot)), eax); 1567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, ecx); 1571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, target); 1574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(edx, Factory::the_hole_value()); 1575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment and issue the write barrier. 1578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(target, eax); 1579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The value of the assignment is in eax. RecordWrite clobbers its 1580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // register arguments. 1581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, eax); 1582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(ecx, offset, edx, ebx); 1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call the runtime for the assignment. The runtime will ignore 1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // const reinitialization. 1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Value. 1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(esi); // Context. 1592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 1593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime will ignore const redeclaration. 1595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, eax); 16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1608d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 16133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(esp, kPointerSize)); // Receiver is now under value. 1620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ecx, prop->key()->AsLiteral()->handle()); 16274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (expr->ends_initialization_block()) { 16284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(edx, Operand(esp, 0)); 16294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 16304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(edx); 16314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 1635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(eax); // Result of assignment, saved even if not needed. 1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(esp, kPointerSize)); // Receiver is under value. 1640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(eax); 16424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke DropAndApply(1, context_, eax); 16434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 16444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, eax); 1645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1649d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(esp, 2 * kPointerSize)); 1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 16636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 16646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (expr->ends_initialization_block()) { 16656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. 16666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 16676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 16686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This nop signals to the IC that there is no inlined code at the call 1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // site for it to patch. 1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ nop(); 1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 1680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(eax); // Result of assignment, saved even if not needed. 16816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(eax); 1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 16866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Apply(context_, eax); 1687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1690d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 1695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(expr->obj(), kAccumulator); 1696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 1697402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, eax); 1698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(expr->obj(), kStack); 1700402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(expr->key(), kAccumulator); 1701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(edx); 1702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, eax); 1704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 1709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Object> name, 1710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 17133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 17143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 1715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 17163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Set(ecx, Immediate(name)); 1718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source position of the IC call. 17193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SetSourcePosition(expr->position()); 1720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 1722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, mode); 1723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, eax); 1726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 17307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Expression* key, 17317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch RelocInfo::Mode mode) { 17327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Code common for calls using the IC. 17337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 17347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int arg_count = args->length(); 17357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch for (int i = 0; i < arg_count; i++) { 17367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(i), kStack); 17377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 17387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(key, kAccumulator); 17397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ecx, eax); 17407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Record source position of the IC call. 17417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch SetSourcePosition(expr->position()); 17427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 17437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize( 17447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch arg_count, in_loop); 17457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ call(ic, mode); 17467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Restore context register. 17477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 17487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, eax); 17497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 17507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1752d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 1753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 17643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 17653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, eax); 1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1770d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 1771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 1772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 1773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 1774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 1776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 1777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // resolve the function we need to call and the receiver of the 1778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. Then we call the resolved function using the given 1779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 1780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(fun, kStack); 1781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Factory::undefined_value())); // Reserved receiver slot. 1782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the arguments. 1784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 1785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 1786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 1787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(i), kStack); 1788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the function - found below the arguments. 1791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(esp, (arg_count + 1) * kPointerSize)); 1792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the first argument or undefined if it doesn't exist. 1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (arg_count > 0) { 1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(esp, arg_count * kPointerSize)); 1796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Factory::undefined_value())); 1798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the receiver of the enclosing function and do runtime call. 1801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); 1802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 1803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime call returns a pair of values in eax (function) and 1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // edx (receiver). Touch up the stack with the right values. 1806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); 1807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); 1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetSourcePosition(expr->position()); 1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke DropAndApply(1, context_, eax); 1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 1818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Push global object as receiver for the call IC. 1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && var->slot() != NULL && 1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block var->slot()->type() == Slot::LOOKUP) { 1823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call to a lookup slot (dynamically introduced variable). Call the 1824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // runtime to find the function to call (returned in eax) and the object 1825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holding it (returned in edx). 1826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 1827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 1828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 1829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Function. 1830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(edx); // Receiver. 1831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitCallWithStub(expr); 1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 1833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 1834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 1835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 1836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 1837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 1838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 18417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call to a keyed property. 18427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // For a synthetic property use keyed load IC followed by function call, 18437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for a regular property use keyed CallIC. 1844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1845402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (prop->is_synthetic()) { 18467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(prop->key(), kAccumulator); 18477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Record source code position for IC call. 18487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch SetSourcePosition(prop->position()); 1849402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(edx); // We do not need to keep the receiver. 1850402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 18517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 18527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ call(ic, RelocInfo::CODE_TARGET); 18537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // By emitting a nop we make sure that we do not have a "test eax,..." 18547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // instruction after the call as it is treated specially 18557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // by the LoadIC code. 18567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ nop(); 1857402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push result (function). 1858402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 1859402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push Global receiver. 1860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ecx, CodeGenerator::GlobalObject()); 1861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); 18627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitCallWithStub(expr); 1863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 18647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 1865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 18673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 1870d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // also use the full code generator. 1871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 1872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 1873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 1874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 1875d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 1876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(fun, kStack); 1878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 1879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ebx, CodeGenerator::GlobalObject()); 1880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 1881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 1882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 18833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 1892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push function on the stack. 1893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 1894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object (receiver). 1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(CodeGenerator::GlobalObject()); 1897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load function, arg_count into edi and eax. 1910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(eax, Immediate(arg_count)); 1911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Function is in esp[arg_count + 1]. 1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 1913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Replace function on TOS with result in eax, or pop it. 1918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, eax); 1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 1923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 1933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_true); 1934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 1935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 1951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_true); 1952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(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 __ test(eax, Immediate(kSmiTagMask)); 1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_false); 1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::null_value()); 1971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); 1975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_false); 1977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, if_false); 1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(ecx, LAST_JS_OBJECT_TYPE); 1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below_equal, if_true); 1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_false); 2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(ebx, Immediate(1 << Map::kIsUndetectable)); 2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_true); 2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_false); 2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_false); 2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_false); 2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); 2063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 2083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 2084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(Operand(eax, StandardFrameConstants::kContextOffset), 2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &check_frame_marker); 2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset)); 2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset), 2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); 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::EmitObjectEquals(ZoneList<Expression*>* args) { 2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); 2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(ebx); 2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Operand(ebx)); 2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ArgumentsAccessStub expects the key in edx and the formal 2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // parameter count in eax. 2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, eax); 2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); 2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label exit; 2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); 2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), 2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &exit); 2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (FLAG_debug_code) __ AbortIfNotSmi(eax); 2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, &null); 2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, eax); // Map is now in eax. 2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, &null); 2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // As long as JS_FUNCTION_TYPE is the last instance type and it is 2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // LAST_JS_OBJECT_TYPE. 2176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(ebx, JS_FUNCTION_TYPE); 2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &function); 2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the constructor in the map is a function. 2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, Map::kConstructorOffset)); 2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &non_function_constructor); 2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // eax now contains the constructor function. Grab the 2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); 2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset)); 2190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::function_class_symbol()); 2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::Object_symbol()); 2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::null_value()); 2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING 2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif 2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::undefined_value()); 2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); 2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // To allocate a heap number, and ensure that it is not a smi, we 2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call the runtime function FUnaryMinus on 0, returning the double 2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -0.0. A new, distinct heap number is returned each time. 2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Smi::FromInt(0))); 2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kNumberUnaryMinus, 1); 2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edi, eax); 2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(0, ebx); 2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction(ExternalReference::random_uint32_function(), 0); 2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in eax to 0.(32 random bits) in a double 2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is implemented on both SSE2 and FPU. 2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CpuFeatures::IsSupported(SSE2)) { 2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CpuFeatures::Scope fscope(SSE2); 2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm1, Operand(ebx)); 2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm0, Operand(eax)); 2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cvtss2sd(xmm1, xmm1); 2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pxor(xmm0, xmm1); 2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ subsd(xmm0, xmm1); 2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); 2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x4130000000000000 is 1.0 x 2^20 as a double. 2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(FieldOperand(edi, HeapNumber::kExponentOffset), 2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(0x41300000)); 2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax); 2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0)); 2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ fsubp(1); 2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, edi); 2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(3), kStack); 2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); // Load the object. 2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, &done); 2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); 2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_pow, 2); 2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); // Load the object. 2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); // Load the value. 2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(ebx); // eax = value. ebx = object. 2346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(ebx, Immediate(kSmiTagMask)); 2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, &done); 2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); 2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); 2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 2360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, eax); 2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx); 2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 2370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 23867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(eax, ebx); 23877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 23917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 23947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, ebx); 2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 23997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 24007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(0), kStack); 24027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(1), kAccumulator); 24037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = ebx; 24057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = eax; 24067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = ecx; 24077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = edx; 24087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 24107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 24127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 24137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 24157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 24167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch, 24177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 24187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 24217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 24227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 24237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 24267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 24277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 24287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(result, Immediate(Factory::nan_value())); 24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move the undefined value into the result register, which will 24337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 24347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(result, Immediate(Factory::undefined_value())); 24357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 24387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 24397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 24417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, result); 2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 24467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 24477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(0), kStack); 24497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(1), kAccumulator); 24507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = ebx; 24527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = eax; 24537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = ecx; 24547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = edx; 24557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 24567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 24587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 24607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 24617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 24647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 24657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 24667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 24677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 24707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 24717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 24727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 24757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 24767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 24777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(result, Immediate(Factory::empty_string())); 24787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 24817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 24827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(result, Immediate(Smi::FromInt(0))); 24847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 24877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 24887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 24907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, result); 24917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 24927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 2501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke TranscendentalCacheStub stub(TranscendentalCache::SIN); 2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke TranscendentalCacheStub stub(TranscendentalCache::COS); 2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime function. 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sqrt, 1); 2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length() - 2; // For receiver and function. 2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); // Receiver. 2552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(i + 1), kStack); 2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(arg_count + 1), kAccumulator); // Function. 2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // InvokeFunction requires function in edi. Move it in there. 2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!result_register().is(edi)) __ mov(edi, result_register()); 2559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeFunction(edi, count, CALL_FUNCTION); 2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kRegExpConstructResult, 3); 2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kSwapElements, 3); 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Top::global_context()->jsfunction_result_caches()); 2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::undefined_value()); 2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); 2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = eax; 2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = ebx; 2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register tmp = ecx; 2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(cache, CodeGenerator::ContextOperand(esi, Context::GLOBAL_INDEX)); 2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(cache, 2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, GlobalObject::kGlobalContextOffset)); 2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(cache, 2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CodeGenerator::ContextOperand( 2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(cache, 2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, not_found; 2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp)); 2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, ¬_found); 2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1)); 2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(cache); 2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(key); 2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 26453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 26463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 2649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(eax, CodeGenerator::GlobalObject()); 2650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); 2651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 26523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 26533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 26543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 26553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 2656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 2657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the JS runtime function via a call IC. 2661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Set(ecx, Immediate(expr->name())); 2662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 2664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 2665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the C runtime function. 2669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 2670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, eax); 2672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2675d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 2678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->expression()->AsProperty(); 2680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop == NULL && var == NULL) { 2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-property, non-variable reference is true. 2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression may have side effects. 2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, true); 2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var != NULL && 2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke !var->is_global() && 2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke var->slot() != NULL && 2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke var->slot()->type() != Slot::LOOKUP) { 2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-global, non-dynamic variables is false. 2691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression does not have side effects. 2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, false); 2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Property or variable reference. Call the delete builtin with 2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object and property name as arguments. 2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kStack); 2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->is_global()) { 2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(CodeGenerator::GlobalObject()); 2701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-global variable. Call the runtime to look up the context 2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // where the variable was introduced. 2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLookupContext, 2); 2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); 2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, eax); 2713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 2718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 2720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 2721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 2722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 2723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 2725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 2727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 2728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 2729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Factory::undefined_value()); 2730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 2732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(Factory::undefined_value())); 2733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 2737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Value is false so it's needed. 2738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 2739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 2740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Factory::undefined_value()); 2741e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 2743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(Factory::undefined_value())); 2744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through. 2747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 2748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 2749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 2750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 27533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 2756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Notice that the labels are swapped. 2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); 2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForControl(expr->expression(), if_true, if_false); 2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_false, if_true); // Labels swapped. 2767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 2771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (proxy != NULL && 2774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block !proxy->var()->is_this() && 2775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->is_global()) { 2776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "Global variable"); 2777402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, CodeGenerator::GlobalObject()); 2778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ecx, Immediate(proxy->name())); 2779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 2780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Use a regular load, not a contextual load, to avoid a reference 2781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // error. 2782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(ic, RelocInfo::CODE_TARGET); 2783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 2784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (proxy != NULL && 2785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot() != NULL && 2786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot()->type() == Slot::LOOKUP) { 2787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(esi); 2788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(proxy->name())); 2789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(eax); 2791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This expression cannot throw a reference error at the top level. 2793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 2797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, eax); 2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2801d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 2802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 2803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke VisitForValue(expr->expression(), kAccumulator); 2804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 2805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ test(result_register(), Immediate(kSmiTagMask)); 2806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(zero, &no_conversion); 2807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(result_register()); 2808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 2809d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 2810d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context_, result_register()); 2811d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 2812d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2813d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 28144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 28154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 28164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool overwrite = 28174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 28184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 28194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::SUB, overwrite); 28204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 28214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register eax. 28224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 28234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 28244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, eax); 28254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 28264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 28274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 28284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 28294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 28304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool overwrite = 28314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 28324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 28334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); 28344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 28354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register eax. 28364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 28374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Avoid calling the stub for Smis. 28384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Label smi, done; 28394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ test(result_register(), Immediate(kSmiTagMask)); 28404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ j(zero, &smi); 28414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Non-smi: call stub leaving result in accumulator register. 28424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 28434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ jmp(&done); 28444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Perform operation directly on Smis. 28454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&smi); 28464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ not_(result_register()); 28474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ and_(result_register(), ~kSmiTagMask); // Remove inverted smi-tag. 28484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 28494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, result_register()); 28504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 28514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 28524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 28553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2859d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CountOperation"); 2861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 2862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // as the left-hand side. 2863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 2864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 2869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 2870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 2872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 2874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 2875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 2876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 2877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 2878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 2881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 2882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 2883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Location saved_location = location_; 2884d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke location_ = kAccumulator; 2885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 2886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kValue); 2887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke location_ = saved_location; 2888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 2890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix() && context_ != Expression::kEffect) { 2891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(Smi::FromInt(0))); 2892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 2894402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Put the object both on the stack and in the accumulator. 2895402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kAccumulator); 2896402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 2897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 2898e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 2900402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->key(), kAccumulator); 2901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edx, Operand(esp, 0)); 2902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 2903e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 2904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2906e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 2908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 2909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(zero, &no_conversion); 2911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(eax); 2912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 2913d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 29143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 2916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 2918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 2919e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 2920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 2921e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do not save result. 2922e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 2924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 2925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 2926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 2927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the result on the stack. If we have a named or keyed property 2928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // we store the result under the receiver that is currently on top 2929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the stack. 2930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 2931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 2932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(eax); 2933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: 2935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(esp, kPointerSize), eax); 2936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: 2938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(esp, 2 * kPointerSize), eax); 2939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2945d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 2946d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 2947d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (loop_depth() > 0) { 2948d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 2949d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ add(Operand(eax), Immediate(Smi::FromInt(1))); 2950d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 2951d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 2952d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2953d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(overflow, &stub_call); 2954d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 2955d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 2956d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2957d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(zero, &done); 2958d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 2959d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 2960d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 2961d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 2962d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 2963d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ add(Operand(eax), Immediate(Smi::FromInt(1))); 2964d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2965d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 2967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(expr->binary_op(), 2968e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 29696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NO_GENERIC_BINARY_FLAGS, 29706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block TypeInfo::Unknown()); 2971d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke stub.GenerateCall(masm(), eax, Smi::FromInt(1)); 2972d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 2973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2974e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in eax. 2975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 2976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 2977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 2979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 2980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::ASSIGN, 2981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kEffect); 2982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 2984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 2985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 2986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 2989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::ASSIGN, 2991e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke context_); 2992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 2995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ecx, prop->key()->AsLiteral()->handle()); 29964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(edx); 2997e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 2999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // This nop signals to the IC that there is no inlined code at the call 3000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // site for it to patch. 3001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 3002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 3003e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 3004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 3005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 30074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, eax); 3008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 30126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 30136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 3014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ call(ic, RelocInfo::CODE_TARGET); 3016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // This nop signals to the IC that there is no inlined code at the call 3017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // site for it to patch. 3018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ nop(); 3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 30206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Result is on the stack 3021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 3023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 30256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Apply(context_, eax); 3026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3028d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 30293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 30303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 30313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 30323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 3034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ BinaryOperation"); 3035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::COMMA: 3037e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->left()); 3038d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Visit(expr->right()); 3039d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3041d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::OR: 3042d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::AND: 3043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitLogicalOperation(expr); 3044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::ADD: 3047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SUB: 3048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::DIV: 3049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MOD: 3050d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MUL: 3051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_OR: 3052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_AND: 3053d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_XOR: 3054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHL: 3055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHR: 3056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::SAR: 3057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 3058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 3059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitBinaryOp(expr->op(), context_); 3060d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 3064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 30663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 30673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNullCompare(bool strict, 3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register obj, 3070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register null_const, 3071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true, 3072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false, 3073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register scratch) { 3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(obj, Operand(null_const)); 3075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (strict) { 3076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 3077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 3078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 3079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(obj, Factory::undefined_value()); 3080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 3081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(obj, Immediate(kSmiTagMask)); 3082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_false); 3083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // It can be an undetectable object. 3084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(scratch, FieldOperand(obj, HeapObject::kMapOffset)); 3085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); 3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(scratch, Immediate(1 << Map::kIsUndetectable)); 3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_true); 3088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 3090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3093d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 3095e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 3097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 3098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 3102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 3103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 3105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 3107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 3108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(eax, Factory::true_value()); 3110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 3111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3112d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 31133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3114d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 3115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 3116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 3117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ test(eax, Operand(eax)); 3119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, if_true); // The stub returns 0 for true. 3120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 3125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 3126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = no_condition; 3127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 3128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 3130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 3131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through 3132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::EQ: { 3133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = equal; 3134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(edx); 3135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If either operand is constant null we do a fast compare 3136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // against null. 3137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Literal* right_literal = expr->right()->AsLiteral(); 3138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Literal* left_literal = expr->left()->AsLiteral(); 3139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (right_literal != NULL && right_literal->handle()->IsNull()) { 3140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitNullCompare(strict, edx, eax, if_true, if_false, ecx); 3141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 3142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (left_literal != NULL && left_literal->handle()->IsNull()) { 3144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitNullCompare(strict, eax, edx, if_true, if_false, ecx); 3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 3151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 3152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(edx); 3153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 3155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 3156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 3157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edx, result_register()); 3158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(eax); 3159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 3161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 3162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 3163e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edx, result_register()); 3164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(eax); 3165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 3167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 3168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(edx); 3169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 3171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 3172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 3174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The comparison stub expects the smi vs. smi case to be handled 3177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // before it is called. 3178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label slow_case; 3179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ecx, Operand(edx)); 3180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ or_(ecx, Operand(eax)); 3181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ test(ecx, Immediate(kSmiTagMask)); 3182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ j(not_zero, &slow_case, not_taken); 3183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(edx, Operand(eax)); 3184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(cc, if_true); 3185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&slow_case); 3188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CompareStub stub(cc, strict); 3189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ test(eax, Operand(eax)); 3191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(cc, if_true); 3192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 31943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 31953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 3197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 3198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_true, if_false); 3199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3202d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 3203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 3204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, eax); 3205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return eax; } 3209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return esi; } 3212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 3216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(ebp, frame_offset), value); 32173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 32183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 32193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(dst, CodeGenerator::ContextOperand(esi, context_index)); 3222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 3226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 3227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3228d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 3229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address on top of stack (smi encoded Code* delta) 3230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(edx)); 3231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edx, Operand(esp, 0)); 3232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(Operand(edx), Immediate(masm_->CodeObject())); 3233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 3234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 3235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(edx, Operand(edx)); // Convert to smi. 3236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(esp, 0), edx); 3237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 3238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 3239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3242d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 3243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(edx)); 3244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 3245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 3246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address. 3247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edx, Operand(esp, 0)); 3248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sar(edx, 1); // Convert smi to int. 3249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(Operand(edx), Immediate(masm_->CodeObject())); 3250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(esp, 0), edx); 3251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // And return. 3252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 3253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __ 3257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 32583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 3259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 3261