full-codegen-ia32.cc revision db5a90a88cfcddb042912799e872037c6548b8a3
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 3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h" 333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h" 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h" 35e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include "debug.h" 36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h" 373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h" 386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h" 398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#include "stub-cache.h" 403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the 483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them. The actual argument count matches the 493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function. 503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o edi: the JS function object being called (ie, ourselves) 533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o esi: our context 543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o ebp: our caller's frame pointer 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o esp: stack pointer (pointing to return address) 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-ia32.h for its layout. 59756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::Generate(CompilationInfo* info) { 603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(info_ == NULL); 613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu info_ = info; 623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 65f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG 66f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (strlen(FLAG_stop_at) > 0 && 67f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 68f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ int3(); 69f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 70f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif 71f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 72756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(ebp); // Caller's frame pointer. 73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(ebp, esp); 74756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(esi); // Callee's context. 75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(edi); // Callee's JS Function. 76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int locals_count = scope()->num_stack_slots(); 79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (locals_count == 1) { 80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(Immediate(Factory::undefined_value())); 81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (locals_count > 1) { 82756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(eax, Immediate(Factory::undefined_value())); 83756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < locals_count; i++) { 84756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(eax); 85d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 86d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 87756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 88d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 89756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bool function_in_register = true; 904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 91756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 92756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots > 0) { 94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate local context"); 95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Argument to NewContext is the function, which is still in edi. 96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(edi); 97756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots <= FastNewContextStub::kMaximumSlots) { 98756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastNewContextStub stub(heap_slots); 99756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallRuntime(Runtime::kNewContext, 1); 102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick function_in_register = false; 104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Context is returned in both eax and esi. It replaces the context 105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // passed to us. It's saved in the stack and kept live in esi. 106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 108756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy parameters into context if necessary. 109756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int num_parameters = scope()->num_parameters(); 110756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < num_parameters; i++) { 1110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = scope()->parameter(i)->AsSlot(); 112756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (slot != NULL && slot->type() == Slot::CONTEXT) { 113756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int parameter_offset = StandardFrameConstants::kCallerSPOffset + 114756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick (num_parameters - 1 - i) * kPointerSize; 115756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load parameter from stack. 116756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(eax, Operand(ebp, parameter_offset)); 117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int context_offset = Context::SlotOffset(slot->index()); 119756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(Operand(esi, context_offset), eax); 120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Update the write barrier. This clobbers all involved 121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // registers, so we have use a third register to avoid 122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // clobbering esi. 123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(ecx, esi); 124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ RecordWrite(ecx, context_offset, eax, ebx); 125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 1283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Variable* arguments = scope()->arguments(); 130756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (arguments != NULL) { 131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Function uses arguments object. 132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate arguments object"); 133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (function_in_register) { 134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(edi); 135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Receiver is just before the parameters on the caller's stack. 139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int offset = scope()->num_parameters() * kPointerSize; 140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ lea(edx, 141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); 142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(edx); 143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(Immediate(Smi::FromInt(scope()->num_parameters()))); 144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments to ArgumentsAccessStub: 145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // function, receiver address, parameter count. 146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The stub will rewrite receiver and parameter count if the previous 147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // stack frame was an arguments adapter frame. 148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(ecx, eax); // Duplicate result. 1510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Move(arguments->AsSlot(), eax, ebx, edx); 1520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); 153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Move(dot_arguments_slot, ecx, ebx, edx); 154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block { Comment cmnt(masm_, "[ Declarations"); 157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // For named function expressions, declare the function name as a 158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant. 159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && scope()->function() != NULL) { 160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(scope()->function(), Variable::CONST, NULL); 161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Visit all the explicit declarations unless there is an illegal 163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // redeclaration. 164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->HasIllegalRedeclaration()) { 165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke scope()->VisitIllegalRedeclaration(this); 166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitDeclarations(scope()->declarations()); 168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Stack check"); 1720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel ok; 173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::address_of_stack_limit(); 175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(esp, Operand::StaticVariable(stack_limit)); 1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &ok, taken); 1773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block StackCheckStub stub; 1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallStub(&stub); 1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&ok); 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceEnter, 0); 1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Body"); 187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu VisitStatements(function()->body()); 189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit a 'return undefined' in case control fell off the end of the body. 1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, Factory::undefined_value()); 1957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 200db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() { 201db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch __ Set(eax, Immediate(Smi::FromInt(0))); 202db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch} 203db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 204db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 2057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Common return label 211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(eax); 2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 221bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 2223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ RecordJSReturn(); 2233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Do not use the leave instruction here because it is too short to 2243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // patch with the code required by the debugger. 2253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(esp, ebp); 2263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(ebp); 2273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ ret((scope()->num_parameters() + 1) * kPointerSize); 228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check that the size of the code used for returning matches what is 230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expected by the debugger. 231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(Assembler::kJSReturnSequenceLength, 23280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 23880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenFullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( 23980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, Expression* left, Expression* right) { 24080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(ShouldInlineSmiCase(op)); 24180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (op == Token::DIV || op == Token::MOD || op == Token::MUL) { 24280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // We never generate inlined constant smi operations for these. 24380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return kNoConstants; 24480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (right->IsSmiLiteral()) { 24580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return kRightConstant; 24680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (left->IsSmiLiteral() && !Token::IsShiftOp(op)) { 24780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return kLeftConstant; 24880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 24980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return kNoConstants; 25080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 25180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 25280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 25380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2540d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Slot* slot) const { 2550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2580d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { 2590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 2600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), slot_operand); 2610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2640d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { 2650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 2660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Memory operands can be pushed directly. 2670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(slot_operand); 268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2710d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Slot* slot) const { 2720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 2730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->Move(result_register(), slot); 2740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 2750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 2790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen UNREACHABLE(); // Not used on IA32. 280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2830d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 2840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 2850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen UNREACHABLE(); // Not used on IA32. 2860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 2910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen UNREACHABLE(); // Not used on IA32. 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2950d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 2960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen UNREACHABLE(); // Not used on IA32. 2970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3000d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 3010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3040d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 3050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), lit); 3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3100d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 3110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Immediates can be pushed directly. 3120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(Immediate(lit)); 3130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 3170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 3190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(false_label_); 3200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsTrue() || lit->IsJSObject()) { 3210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(true_label_); 3220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 3230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 3240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(false_label_); 3250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(true_label_); 3270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 3290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 3300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(false_label_); 3310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(true_label_); 3330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 3360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), lit); 3370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3420d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count, 3430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 3450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3490d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 3500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int count, 3510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 3550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3580d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 3590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count > 1) __ Drop(count - 1); 3620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(Operand(esp, 0), reg); 363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3660d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count, 3670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 3700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 3720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 3730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3760d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 3770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 3780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT_EQ(materialize_true, materialize_false); 3790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 3800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3830d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 3840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 3850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 3860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done; 3870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 3880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Factory::true_value()); 3890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 3900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 3910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Factory::false_value()); 3920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3960d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 3970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 3990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done; 4000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 4010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(Immediate(Factory::true_value())); 4020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 4030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(Immediate(Factory::false_value())); 4050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 4060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4090d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 4100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 4110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(materialize_false == false_label_); 4120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(materialize_true == true_label_); 4130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const { 4170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> value = 4220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Factory::true_value() : Factory::false_value(); 4230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), value); 4240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> value = 4290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Factory::true_value() : Factory::false_value(); 4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(Immediate(value)); 4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 4350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 4360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ jmp(true_label_); 4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 4380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ jmp(false_label_); 439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 44380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::DoTest(Label* if_true, 44480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 44580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the inlined tests assumed by the stub. 447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(result_register(), Factory::undefined_value()); 448e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(result_register(), Factory::true_value()); 450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_true); 451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(result_register(), Factory::false_value()); 452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, if_false); 453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(result_register(), Operand(result_register())); 455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, if_false); 456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(result_register(), Immediate(kSmiTagMask)); 457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, if_true); 458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the ToBoolean stub for all other cases. 460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ToBooleanStub stub; 461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(eax, Operand(eax)); 464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 46580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns nonzero for true. 46680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 46780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 47080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc, 47180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 47280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 47380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 47480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 47580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 47680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 47780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(NegateCondition(cc), if_false); 47880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 47980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 48080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(if_false); 481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (slot->type()) { 487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOCAL: 489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(ebp, SlotOffset(slot)); 490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::CONTEXT: { 491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int context_chain_length = 4923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->ContextChainLength(slot->var()->scope()); 493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadContext(scratch, context_chain_length); 49459151504615d929945dc59db37bf1166937748c6Steve Block return ContextOperand(scratch, slot->index()); 495d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOOKUP: 497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Operand(eax, 0); 501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) { 505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(source, destination); 506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(destination, location); 507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst, 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register src, 512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2) { 514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!scratch1.is(src) && !scratch2.is(src)); 516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(dst, scratch1); 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(location, src); 518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (dst->type() == Slot::CONTEXT) { 520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(scratch1, offset, src, scratch2); 522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable, 527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable::Mode mode, 528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FunctionLiteral* function) { 529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(variable != NULL); // Must have been resolved. 5310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = variable->AsSlot(); 532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = variable->AsProperty(); 533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(ebp, SlotOffset(slot)), 539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Immediate(Factory::the_hole_value())); 540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(ebp, SlotOffset(slot)), result_register()); 543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 55459151504615d929945dc59db37bf1166937748c6Steve Block __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX)); 555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(ebx, Operand(esi)); 556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(equal, "Unexpected declaration in current context."); 557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 55959151504615d929945dc59db37bf1166937748c6Steve Block __ mov(ContextOperand(esi, slot->index()), 560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(Factory::the_hole_value())); 561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the hole value is in old space. 562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 56459151504615d929945dc59db37bf1166937748c6Steve Block __ mov(ContextOperand(esi, slot->index()), result_register()); 565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 5664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(ebx, esi); 5674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(ebx, offset, result_register(), ecx); 568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(esi); 573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(variable->name())); 574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(mode == Variable::VAR || mode == Variable::CONST); 576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; 577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(Smi::FromInt(attr))); 578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(Factory::the_hole_value())); 584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(function); 586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(Smi::FromInt(0))); // No initial value! 588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL || mode == Variable::CONST) { 596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL) { 6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->key()); 6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 6040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, result_register()); 606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Factory::the_hole_value()); 607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 6110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 6133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 6143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 6233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 6243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(esi); // The context is the first argument. 6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(pairs)); 6263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 6293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 6570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 65980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, Operand(esp, 0)); // Switch value. 6610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 6620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 6630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel slow_case; 66480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(ecx, edx); 66580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ or_(ecx, Operand(eax)); 66680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(ecx, Immediate(kSmiTagMask)); 66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, &slow_case, not_taken); 66880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(edx, Operand(eax)); 66980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &next_test); 67080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 67180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(clause->body_target()->entry_label()); 67280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareFlags flags = inline_smi_code 6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_SMI_COMPARE_IN_STUB 6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_COMPARE_FLAGS; 6780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareStub stub(equal, true, flags); 679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Operand(eax)); 681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(clause->body_target()->entry_label()); 684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 6853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(nested_statement.break_target()); 692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(default_clause->body_target()->entry_label()); 694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(clause->body_target()->entry_label()); 701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(nested_statement.break_target()); 705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the object to enumerate over. Both SpiderMonkey and JSC 717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ignore null and undefined in contrast to the specification; see 718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ECMA-262 section 12.6.4. 7190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::undefined_value()); 721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::null_value()); 723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 7260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel convert, done_convert; 727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, &convert); 729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, &done_convert); 731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); 733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); 7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 73759151504615d929945dc59db37bf1166937748c6Steve Block // Check cache validity in generated code. This is a fast case for 73859151504615d929945dc59db37bf1166937748c6Steve Block // the JSObject::IsSimpleEnum cache validity checks. If we cannot 73959151504615d929945dc59db37bf1166937748c6Steve Block // guarantee cache validity, call the runtime system to check cache 74059151504615d929945dc59db37bf1166937748c6Steve Block // validity or get the property names in a fixed array. 74159151504615d929945dc59db37bf1166937748c6Steve Block Label next, call_runtime; 74259151504615d929945dc59db37bf1166937748c6Steve Block __ mov(ecx, eax); 74359151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&next); 74459151504615d929945dc59db37bf1166937748c6Steve Block 74559151504615d929945dc59db37bf1166937748c6Steve Block // Check that there are no elements. Register ecx contains the 74659151504615d929945dc59db37bf1166937748c6Steve Block // current JS object we've reached through the prototype chain. 74759151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(FieldOperand(ecx, JSObject::kElementsOffset), 74859151504615d929945dc59db37bf1166937748c6Steve Block Factory::empty_fixed_array()); 74959151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, &call_runtime); 75059151504615d929945dc59db37bf1166937748c6Steve Block 75159151504615d929945dc59db37bf1166937748c6Steve Block // Check that instance descriptors are not empty so that we can 75259151504615d929945dc59db37bf1166937748c6Steve Block // check for an enum cache. Leave the map in ebx for the subsequent 75359151504615d929945dc59db37bf1166937748c6Steve Block // prototype load. 75459151504615d929945dc59db37bf1166937748c6Steve Block __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); 75559151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset)); 75659151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(edx, Factory::empty_descriptor_array()); 75759151504615d929945dc59db37bf1166937748c6Steve Block __ j(equal, &call_runtime); 75859151504615d929945dc59db37bf1166937748c6Steve Block 75959151504615d929945dc59db37bf1166937748c6Steve Block // Check that there in an enum cache in the non-empty instance 76059151504615d929945dc59db37bf1166937748c6Steve Block // descriptors (edx). This is the case if the next enumeration 76159151504615d929945dc59db37bf1166937748c6Steve Block // index field does not contain a smi. 76259151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); 76359151504615d929945dc59db37bf1166937748c6Steve Block __ test(edx, Immediate(kSmiTagMask)); 76459151504615d929945dc59db37bf1166937748c6Steve Block __ j(zero, &call_runtime); 76559151504615d929945dc59db37bf1166937748c6Steve Block 76659151504615d929945dc59db37bf1166937748c6Steve Block // For all objects but the receiver, check that the cache is empty. 7670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel check_prototype; 76859151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(ecx, Operand(eax)); 76959151504615d929945dc59db37bf1166937748c6Steve Block __ j(equal, &check_prototype); 77059151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 77159151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(edx, Factory::empty_fixed_array()); 77259151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, &call_runtime); 77359151504615d929945dc59db37bf1166937748c6Steve Block 77459151504615d929945dc59db37bf1166937748c6Steve Block // Load the prototype from the map and loop if non-null. 77559151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&check_prototype); 77659151504615d929945dc59db37bf1166937748c6Steve Block __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); 77759151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(ecx, Factory::null_value()); 77859151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, &next); 77959151504615d929945dc59db37bf1166937748c6Steve Block 78059151504615d929945dc59db37bf1166937748c6Steve Block // The enum cache is valid. Load the map of the object being 78159151504615d929945dc59db37bf1166937748c6Steve Block // iterated over and use the cache for the iteration. 7820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel use_cache; 78359151504615d929945dc59db37bf1166937748c6Steve Block __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 78459151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(&use_cache); 785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 78759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&call_runtime); 788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Duplicate the enumerable object on the stack. 789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 7940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel fixed_array; 795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map()); 796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &fixed_array); 797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register eax. Get the enumeration cache from it. 79959151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&use_cache); 800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); 801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); 802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Setup the four remaining stack slots. 805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Map. 806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(edx); // Enumeration cache. 807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); 808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Enumeration cache length (as smi). 809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Smi::FromInt(0))); // Initial index. 810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register eax. Iterate through that. 813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Smi::FromInt(0))); // Map (0) - force slow check. 815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); 816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Fixed array length (as smi). 818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(Smi::FromInt(0))); // Initial index. 819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index. 823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length. 824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, loop_statement.break_target()); 825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register ebx. 827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, Operand(esp, 2 * kPointerSize)); 828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); 829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the expected map from the stack or a zero map in the 831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register edx. 832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, Operand(esp, 3 * kPointerSize)); 833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If not, we have to filter the key. 8360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel update_each; 837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, Operand(esp, 4 * kPointerSize)); 838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &update_each); 840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the entry to a string or null if it isn't a property 842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // anymore. If the property has been removed while iterating, we 843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ecx); // Enumerable. 845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ebx); // Current entry. 846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 847756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ test(eax, Operand(eax)); 848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, loop_statement.continue_target()); 849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, Operand(eax)); 850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register ebx. 853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(result_register(), ebx); 855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitAssignment(stmt->each()); 857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 8590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label stack_limit_hit; 8600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel stack_check_done; 861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ StackLimitCheck(&stack_limit_hit); 864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_check_done); 865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for going to the next element by incrementing the 867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // index (smi) stored on top of the stack. 868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.continue_target()); 869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); 870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Slow case for the stack limit check. 873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StackCheckStub stack_check_stub; 874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_limit_hit); 875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stack_check_stub); 876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&stack_check_done); 877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.break_target()); 880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(Operand(esp), Immediate(5 * kPointerSize)); 881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 8888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 8898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang bool pretenure) { 890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // space for nested functions that don't need literals cloning. 8928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (scope()->is_function_scope() && 8938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang info->num_literals() == 0 && 8948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang !pretenure) { 895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastNewClosureStub stub; 896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(info)); 897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(esi); 900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(info)); 9018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(Immediate(pretenure 9028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ? Factory::true_value() 9038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang : Factory::false_value())); 9048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CallRuntime(Runtime::kNewClosure, 3); 905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 9060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 9073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 9083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 9113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 9120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->var()); 913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 91659151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( 91759151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 91859151504615d929945dc59db37bf1166937748c6Steve Block TypeofState typeof_state, 91959151504615d929945dc59db37bf1166937748c6Steve Block Label* slow) { 92059151504615d929945dc59db37bf1166937748c6Steve Block Register context = esi; 92159151504615d929945dc59db37bf1166937748c6Steve Block Register temp = edx; 92259151504615d929945dc59db37bf1166937748c6Steve Block 92359151504615d929945dc59db37bf1166937748c6Steve Block Scope* s = scope(); 92459151504615d929945dc59db37bf1166937748c6Steve Block while (s != NULL) { 92559151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 92659151504615d929945dc59db37bf1166937748c6Steve Block if (s->calls_eval()) { 92759151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 92859151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), 92959151504615d929945dc59db37bf1166937748c6Steve Block Immediate(0)); 93059151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 93159151504615d929945dc59db37bf1166937748c6Steve Block } 93259151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 93359151504615d929945dc59db37bf1166937748c6Steve Block __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX)); 93459151504615d929945dc59db37bf1166937748c6Steve Block __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset)); 93559151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering esi. 93659151504615d929945dc59db37bf1166937748c6Steve Block context = temp; 93759151504615d929945dc59db37bf1166937748c6Steve Block } 93859151504615d929945dc59db37bf1166937748c6Steve Block // If no outer scope calls eval, we do not need to check more 93959151504615d929945dc59db37bf1166937748c6Steve Block // context extensions. If we have reached an eval scope, we check 94059151504615d929945dc59db37bf1166937748c6Steve Block // all extensions from this point. 94159151504615d929945dc59db37bf1166937748c6Steve Block if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; 94259151504615d929945dc59db37bf1166937748c6Steve Block s = s->outer_scope(); 94359151504615d929945dc59db37bf1166937748c6Steve Block } 94459151504615d929945dc59db37bf1166937748c6Steve Block 94559151504615d929945dc59db37bf1166937748c6Steve Block if (s != NULL && s->is_eval_scope()) { 94659151504615d929945dc59db37bf1166937748c6Steve Block // Loop up the context chain. There is no frame effect so it is 94759151504615d929945dc59db37bf1166937748c6Steve Block // safe to use raw labels here. 9480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel next, fast; 94959151504615d929945dc59db37bf1166937748c6Steve Block if (!context.is(temp)) { 95059151504615d929945dc59db37bf1166937748c6Steve Block __ mov(temp, context); 95159151504615d929945dc59db37bf1166937748c6Steve Block } 95259151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&next); 95359151504615d929945dc59db37bf1166937748c6Steve Block // Terminate at global context. 95459151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(FieldOperand(temp, HeapObject::kMapOffset), 95559151504615d929945dc59db37bf1166937748c6Steve Block Immediate(Factory::global_context_map())); 95659151504615d929945dc59db37bf1166937748c6Steve Block __ j(equal, &fast); 95759151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 95859151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); 95959151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 96059151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 96159151504615d929945dc59db37bf1166937748c6Steve Block __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX)); 96259151504615d929945dc59db37bf1166937748c6Steve Block __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset)); 96359151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(&next); 96459151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&fast); 96559151504615d929945dc59db37bf1166937748c6Steve Block } 96659151504615d929945dc59db37bf1166937748c6Steve Block 96759151504615d929945dc59db37bf1166937748c6Steve Block // All extension objects were empty and it is safe to use a global 96859151504615d929945dc59db37bf1166937748c6Steve Block // load IC call. 9698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(eax, GlobalObjectOperand()); 97059151504615d929945dc59db37bf1166937748c6Steve Block __ mov(ecx, slot->var()->name()); 97159151504615d929945dc59db37bf1166937748c6Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 97259151504615d929945dc59db37bf1166937748c6Steve Block RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 97359151504615d929945dc59db37bf1166937748c6Steve Block ? RelocInfo::CODE_TARGET 97459151504615d929945dc59db37bf1166937748c6Steve Block : RelocInfo::CODE_TARGET_CONTEXT; 9750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 97659151504615d929945dc59db37bf1166937748c6Steve Block} 97759151504615d929945dc59db37bf1166937748c6Steve Block 97859151504615d929945dc59db37bf1166937748c6Steve Block 97959151504615d929945dc59db37bf1166937748c6Steve BlockMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( 98059151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 98159151504615d929945dc59db37bf1166937748c6Steve Block Label* slow) { 98259151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(slot->type() == Slot::CONTEXT); 98359151504615d929945dc59db37bf1166937748c6Steve Block Register context = esi; 98459151504615d929945dc59db37bf1166937748c6Steve Block Register temp = ebx; 98559151504615d929945dc59db37bf1166937748c6Steve Block 98659151504615d929945dc59db37bf1166937748c6Steve Block for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { 98759151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 98859151504615d929945dc59db37bf1166937748c6Steve Block if (s->calls_eval()) { 98959151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 99059151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), 99159151504615d929945dc59db37bf1166937748c6Steve Block Immediate(0)); 99259151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 99359151504615d929945dc59db37bf1166937748c6Steve Block } 99459151504615d929945dc59db37bf1166937748c6Steve Block __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX)); 99559151504615d929945dc59db37bf1166937748c6Steve Block __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset)); 99659151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering esi. 99759151504615d929945dc59db37bf1166937748c6Steve Block context = temp; 99859151504615d929945dc59db37bf1166937748c6Steve Block } 99959151504615d929945dc59db37bf1166937748c6Steve Block } 100059151504615d929945dc59db37bf1166937748c6Steve Block // Check that last extension is NULL. 100159151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); 100259151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 100359151504615d929945dc59db37bf1166937748c6Steve Block __ mov(temp, ContextOperand(context, Context::FCONTEXT_INDEX)); 100459151504615d929945dc59db37bf1166937748c6Steve Block return ContextOperand(temp, slot->index()); 100559151504615d929945dc59db37bf1166937748c6Steve Block} 100659151504615d929945dc59db37bf1166937748c6Steve Block 100759151504615d929945dc59db37bf1166937748c6Steve Block 100859151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( 100959151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 101059151504615d929945dc59db37bf1166937748c6Steve Block TypeofState typeof_state, 101159151504615d929945dc59db37bf1166937748c6Steve Block Label* slow, 101259151504615d929945dc59db37bf1166937748c6Steve Block Label* done) { 101359151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast-case code for variables that might be shadowed by 101459151504615d929945dc59db37bf1166937748c6Steve Block // eval-introduced variables. Eval is used a lot without 101559151504615d929945dc59db37bf1166937748c6Steve Block // introducing variables. In those cases, we do not want to 101659151504615d929945dc59db37bf1166937748c6Steve Block // perform a runtime call for all variables in the scope 101759151504615d929945dc59db37bf1166937748c6Steve Block // containing the eval. 101859151504615d929945dc59db37bf1166937748c6Steve Block if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 101959151504615d929945dc59db37bf1166937748c6Steve Block EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); 102059151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 102159151504615d929945dc59db37bf1166937748c6Steve Block } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { 10220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); 102359151504615d929945dc59db37bf1166937748c6Steve Block Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); 102459151504615d929945dc59db37bf1166937748c6Steve Block if (potential_slot != NULL) { 102559151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast case for locals that rewrite to slots. 102659151504615d929945dc59db37bf1166937748c6Steve Block __ mov(eax, 102759151504615d929945dc59db37bf1166937748c6Steve Block ContextSlotOperandCheckExtensions(potential_slot, slow)); 102859151504615d929945dc59db37bf1166937748c6Steve Block if (potential_slot->var()->mode() == Variable::CONST) { 102959151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(eax, Factory::the_hole_value()); 103059151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, done); 103159151504615d929945dc59db37bf1166937748c6Steve Block __ mov(eax, Factory::undefined_value()); 103259151504615d929945dc59db37bf1166937748c6Steve Block } 103359151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 103459151504615d929945dc59db37bf1166937748c6Steve Block } else if (rewrite != NULL) { 103559151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast case for calls of an argument function. 103659151504615d929945dc59db37bf1166937748c6Steve Block Property* property = rewrite->AsProperty(); 103759151504615d929945dc59db37bf1166937748c6Steve Block if (property != NULL) { 103859151504615d929945dc59db37bf1166937748c6Steve Block VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 103959151504615d929945dc59db37bf1166937748c6Steve Block Literal* key_literal = property->key()->AsLiteral(); 104059151504615d929945dc59db37bf1166937748c6Steve Block if (obj_proxy != NULL && 104159151504615d929945dc59db37bf1166937748c6Steve Block key_literal != NULL && 104259151504615d929945dc59db37bf1166937748c6Steve Block obj_proxy->IsArguments() && 104359151504615d929945dc59db37bf1166937748c6Steve Block key_literal->handle()->IsSmi()) { 104459151504615d929945dc59db37bf1166937748c6Steve Block // Load arguments object if there are no eval-introduced 104559151504615d929945dc59db37bf1166937748c6Steve Block // variables. Then load the argument from the arguments 104659151504615d929945dc59db37bf1166937748c6Steve Block // object using keyed load. 104759151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, 10480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), 104959151504615d929945dc59db37bf1166937748c6Steve Block slow)); 105059151504615d929945dc59db37bf1166937748c6Steve Block __ mov(eax, Immediate(key_literal->handle())); 105159151504615d929945dc59db37bf1166937748c6Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 10520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 105359151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 105459151504615d929945dc59db37bf1166937748c6Steve Block } 105559151504615d929945dc59db37bf1166937748c6Steve Block } 105659151504615d929945dc59db37bf1166937748c6Steve Block } 105759151504615d929945dc59db37bf1166937748c6Steve Block } 105859151504615d929945dc59db37bf1166937748c6Steve Block} 105959151504615d929945dc59db37bf1166937748c6Steve Block 106059151504615d929945dc59db37bf1166937748c6Steve Block 10610d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitVariableLoad(Variable* var) { 1062d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Four cases: non-this global variables, lookup slots, all other 1063d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // types of slots, and parameters that rewrite to explicit property 1064d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // accesses on the arguments object. 10650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = var->AsSlot(); 1066d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Property* property = var->AsProperty(); 1067d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1068d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (var->is_global() && !var->is_this()) { 10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "Global variable"); 10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use inline caching. Variable name is passed in ecx and the global 10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // object on the stack. 10728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(eax, GlobalObjectOperand()); 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ecx, var->name()); 10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 10750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 10760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 1077d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1078d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 107959151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 108059151504615d929945dc59db37bf1166937748c6Steve Block 108159151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 108259151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 108359151504615d929945dc59db37bf1166937748c6Steve Block EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 108459151504615d929945dc59db37bf1166937748c6Steve Block 108559151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 1086d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Lookup slot"); 1087d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(esi); // Context. 1088d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(Immediate(var->name())); 1089d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 109059151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 109159151504615d929945dc59db37bf1166937748c6Steve Block 10920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 1093d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1094d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL) { 1095d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1096d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ? "Context slot" 1097d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : "Stack slot"); 1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (var->mode() == Variable::CONST) { 1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Constants may be the hole value if they have not been initialized. 1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Unhole them. 11010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done; 1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke MemOperand slot_operand = EmitSlotSearch(slot, eax); 1103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, slot_operand); 1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::the_hole_value()); 1105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::undefined_value()); 1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 11080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 11100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(slot); 1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1113d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Rewritten parameter"); 1115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(property); 1116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Rewritten parameter accesses are of the form "slot[literal]". 1117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the object is in a slot. 1119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 1120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_var); 11210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* object_slot = object_var->AsSlot(); 1122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_slot); 1123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the object. 1125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand object_loc = EmitSlotSearch(object_slot, eax); 1126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edx, object_loc); 1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the key is a smi. 1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key_literal = property->key()->AsLiteral(); 1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(key_literal); 1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(key_literal->handle()->IsSmi()); 1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the key. 1134402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, Immediate(key_literal->handle())); 1135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a keyed property load. 1137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 11380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 11390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Drop key and object left on the stack by IC. 11410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 11423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 11480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel materialized; 11493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 11503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // edi = JS function. 1151bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // ecx = literals array. 1152bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // ebx = regexp literal. 1153bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // eax = regexp literal clone. 11543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1155bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 11563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 115780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1158bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(ebx, FieldOperand(ecx, literal_offset)); 1159bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(ebx, Factory::undefined_value()); 1160bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &materialized); 1161bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 11623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create regexp literal using runtime function 11633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Result will be in eax. 1164bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(ecx); 11653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(Smi::FromInt(expr->literal_index()))); 11663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(expr->pattern())); 11673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(expr->flags())); 11683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1169bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(ebx, eax); 1170bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1171bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&materialized); 1172bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1173bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label allocated, runtime_allocate; 1174bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 1175bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&allocated); 1176bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1177bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&runtime_allocate); 1178bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(ebx); 1179bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(Immediate(Smi::FromInt(size))); 1180bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1181bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(ebx); 1182bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1183bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&allocated); 1184bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Copy the content into the newly allocated memory. 1185bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // (Unroll copy loop once for better throughput). 1186bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 1187bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(edx, FieldOperand(ebx, i)); 1188bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); 1189bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(FieldOperand(eax, i), edx); 1190bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(FieldOperand(eax, i + kPointerSize), ecx); 1191bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1192bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if ((size % (2 * kPointerSize)) != 0) { 1193bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(edx, FieldOperand(ebx, size - kPointerSize)); 1194bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(FieldOperand(eax, size - kPointerSize), edx); 1195bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 11960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 1202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); 1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(expr->constant_properties())); 12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(Immediate(Smi::FromInt(expr->fast_elements() ? 1 : 0))); 1207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->depth() > 1) { 12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 12093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4); 1211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in eax. 1215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 12173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Mark all computed expressions that are bound to a key that 12183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // is shadowed by a later occurrence of the same key. For the 12193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // marked expressions, no store code is emitted. 12203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu expr->CalculateEmitStore(); 12213e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 1222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(eax); // Save result on the stack 1230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 12380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(value); 1239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ecx, Immediate(key->handle())); 12404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(edx, Operand(esp, 0)); 12413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 12423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 12433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu EmitCallIC(ic, RelocInfo::CODE_TARGET); 12443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 1249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(esp, 0)); // Duplicate receiver. 12500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 12510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 12523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 12533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ CallRuntime(Runtime::kSetProperty, 3); 12543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 12553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ Drop(3); 12563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::SETTER: 1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::GETTER: 1260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(esp, 0)); // Duplicate receiver. 12610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 1262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? 1263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(1) : 1264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(0))); 12650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 1266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDefineAccessor, 4); 1267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UNREACHABLE(); 1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 12730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 12750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 12763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1280d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 1285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); 12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(expr->constant_elements())); 1290756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) { 1291756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub stub( 1292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); 1293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 1294756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ IncrementCounter(&Counters::cow_arrays_created_stub, 1); 1295756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (expr->depth() > 1) { 1296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1297756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 1298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1300756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub stub( 1301756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub::CLONE_ELEMENTS, length); 1302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 13033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 13113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 13123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 13163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(eax); 13203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Store the subexpression value in the array's elements. 13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ebx, Operand(esp, 0)); // Copy of array literal. 13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); 13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(FieldOperand(ebx, offset), result_register()); 13293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Update the write barrier for the array store. 1331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(ebx, offset, result_register(), ecx); 13323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 13350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 13370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 13383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 1352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 135580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 135680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (property != NULL) { 135780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen assign_type = (property->key()->IsPropertyName()) 135880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? NAMED_PROPERTY 135980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : KEYED_PROPERTY; 1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 13700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(property->obj()); 1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 13730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 13780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 13790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(property->key()); 1380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edx, Operand(esp, 0)); 1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 13830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 13840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->key()); 1385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 13900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 13910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 13920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 13930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->target()->AsVariableProxy()->var()); 13940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 13950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 13960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 13970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 13980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 13990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 14000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 14010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 140480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 140580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ConstantOperand constant = ShouldInlineSmiCase(op) 140680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? GetConstantOperand(op, expr->target(), expr->value()) 140780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : kNoConstants; 140880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(constant == kRightConstant || constant == kNoConstants); 140980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (constant == kNoConstants) { 141080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(eax); // Left operand goes on the stack. 14110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 141280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 141480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 141580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? OVERWRITE_RIGHT 141680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : NO_OVERWRITE; 141780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position() + 1); 14180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 141980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 142080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EmitInlineSmiBinaryOp(expr, 142180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 142280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mode, 142380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->value(), 142580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen constant); 142680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 14270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitBinaryOp(op, mode); 142880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 142980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 14300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 14400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen expr->op()); 1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1452d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ecx, Immediate(key->handle())); 1456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 14570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1461d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 14640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 146880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, 146980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 147080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool left_is_constant_smi, 147180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Smi* value) { 14720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel call_stub; 14730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 147480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ add(Operand(eax), Immediate(value)); 147580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(overflow, &call_stub); 147680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 147780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &done); 147880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 147980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Undo the optimistic add operation and call the shared stub. 148080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&call_stub); 148180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ sub(Operand(eax), Immediate(value)); 148280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = Token::ADD; 148380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); 148480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (left_is_constant_smi) { 148580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(Immediate(value)); 148680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(eax); 148780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 148880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(eax); 148980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(Immediate(value)); 149080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 149180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallStub(&stub); 149280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 14930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 149480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 149580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 149680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 149780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiSub(Expression* expr, 149880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 149980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool left_is_constant_smi, 150080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Smi* value) { 150180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label call_stub, done; 150280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (left_is_constant_smi) { 150380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(ecx, eax); 150480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(eax, Immediate(value)); 150580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ sub(Operand(eax), ecx); 150680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 150780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ sub(Operand(eax), Immediate(value)); 150880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 150980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(overflow, &call_stub); 151080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 151180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &done); 151280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 151380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&call_stub); 151480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (left_is_constant_smi) { 151580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(Immediate(value)); 151680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(ecx); 151780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 151880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Undo the optimistic sub operation. 151980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ add(Operand(eax), Immediate(value)); 152080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 152180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(eax); 152280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(Immediate(value)); 152380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 152480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 152580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = Token::SUB; 152680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); 1527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 152880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 15290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 153080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 153180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 153280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 153380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr, 153480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 153580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 153680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Smi* value) { 153780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label call_stub, smi_case, done; 153880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen int shift_value = value->value() & 0x1f; 153980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 154080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 154180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &smi_case); 154280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 154380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&call_stub); 154480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); 154580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(eax); 154680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(Immediate(value)); 154780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallStub(&stub); 154880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&done); 154980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 155080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&smi_case); 155180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 155280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHL: 155380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (shift_value != 0) { 155480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(edx, eax); 155580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (shift_value > 1) { 155680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ shl(edx, shift_value - 1); 155780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 155880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Convert int result to smi, checking that it is in int range. 155980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(kSmiTagSize == 1); // Adjust code if not the case. 156080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ add(edx, Operand(edx)); 156180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(overflow, &call_stub); 156280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(eax, edx); // Put result back into eax. 156380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 156480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 156580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SAR: 156680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (shift_value != 0) { 156780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ sar(eax, shift_value); 156880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ and_(eax, ~kSmiTagMask); 156980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 157080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 157180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHR: 157280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (shift_value < 2) { 157380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(edx, eax); 157480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(edx); 157580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ shr(edx, shift_value); 157680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(edx, Immediate(0xc0000000)); 157780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, &call_stub); 157880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTag(edx); 157980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(eax, edx); // Put result back into eax. 158080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 158180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(eax); 158280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ shr(eax, shift_value); 158380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTag(eax); 158480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 158580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 158680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen default: 158780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UNREACHABLE(); 158880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 158980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 159080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 15910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 159280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 159380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 159480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 159580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr, 159680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 159780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 159880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Smi* value) { 159980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label smi_case, done; 160080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 160180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &smi_case); 160280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 160380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); 160480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The order of the arguments does not matter for bit-ops with a 160580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // constant operand. 160680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(Immediate(value)); 160780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(eax); 160880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallStub(&stub); 160980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&done); 161080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 161180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&smi_case); 161280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 161380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_OR: 161480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ or_(Operand(eax), Immediate(value)); 161580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 161680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_XOR: 161780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ xor_(Operand(eax), Immediate(value)); 161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 161980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_AND: 162080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ and_(Operand(eax), Immediate(value)); 162180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 162280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen default: 162380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UNREACHABLE(); 162480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 162580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 162680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 16270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 162880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 162980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 163080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 163180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr, 163280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 163380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 163480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool left_is_constant_smi, 163580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Smi* value) { 163680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 163780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_OR: 163880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_XOR: 163980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_AND: 16400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitConstantSmiBitOp(expr, op, mode, value); 164180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 164280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHL: 164380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SAR: 164480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHR: 164580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(!left_is_constant_smi); 16460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitConstantSmiShiftOp(expr, op, mode, value); 164780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 164880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::ADD: 16490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value); 165080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 165180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SUB: 16520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitConstantSmiSub(expr, mode, left_is_constant_smi, value); 165380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 165480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen default: 165580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UNREACHABLE(); 165680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 165780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 165880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 165980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 166080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, 166180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 166280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 166380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 166480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right, 166580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ConstantOperand constant) { 166680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (constant == kRightConstant) { 166780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Smi* value = Smi::cast(*right->AsLiteral()->handle()); 16680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitConstantSmiBinaryOp(expr, op, mode, false, value); 166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return; 167080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (constant == kLeftConstant) { 167180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Smi* value = Smi::cast(*left->AsLiteral()->handle()); 16720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitConstantSmiBinaryOp(expr, op, mode, true, value); 167380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return; 167480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 167580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 167680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Do combined smi check of the operands. Left operand is on the 167780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // stack. Right operand is in eax. 167880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label done, stub_call, smi_case; 167980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ pop(edx); 168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(ecx, eax); 168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ or_(eax, Operand(edx)); 168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &smi_case); 168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 168580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&stub_call); 168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, NO_SMI_CODE_IN_STUB, TypeInfo::Unknown()); 168780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (stub.ArgsInRegistersSupported()) { 168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen stub.GenerateCall(masm_, edx, ecx); 168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(edx); 169180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(ecx); 169280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallStub(&stub); 169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&done); 169580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&smi_case); 169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(eax, edx); // Copy left operand in case of a stub call. 169880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 170080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SAR: 170180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(eax); 170280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(ecx); 170380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ sar_cl(eax); // No checks of result necessary 170480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTag(eax); 170580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 170680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHL: { 170780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label result_ok; 170880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(eax); 170980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(ecx); 171080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ shl_cl(eax); 171180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the *signed* result fits in a smi. 171280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(eax, 0xc0000000); 171380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(positive, &result_ok); 171480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTag(ecx); 171580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&stub_call); 171680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&result_ok); 171780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTag(eax); 171880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 171980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 172080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHR: { 172180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label result_ok; 172280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(eax); 172380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(ecx); 172480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ shr_cl(eax); 172580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(0xc0000000)); 172680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &result_ok); 172780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTag(ecx); 172880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&stub_call); 172980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&result_ok); 173080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiTag(eax); 173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 173280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 173380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::ADD: 173480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ add(eax, Operand(ecx)); 173580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(overflow, &stub_call); 173680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 173780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SUB: 173880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ sub(eax, Operand(ecx)); 173980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(overflow, &stub_call); 174080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 174180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::MUL: { 174280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiUntag(eax); 174380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ imul(eax, Operand(ecx)); 174480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(overflow, &stub_call); 174580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Operand(eax)); 174680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, &done, taken); 174780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(ebx, edx); 174880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ or_(ebx, Operand(ecx)); 174980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(negative, &stub_call); 175080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 175180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 175280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_OR: 175380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ or_(eax, Operand(ecx)); 175480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 175580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_AND: 175680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ and_(eax, Operand(ecx)); 175780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 175880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_XOR: 175980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ xor_(eax, Operand(ecx)); 176080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 176180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen default: 176280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UNREACHABLE(); 176380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 176480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 176580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 17660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 176780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 176880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 176980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 177080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 177180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode) { 177280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen TypeInfo type = TypeInfo::Unknown(); 177380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS, type); 177480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (stub.ArgsInRegistersSupported()) { 177580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ pop(edx); 177680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen stub.GenerateCall(masm_, edx, eax); 177780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 177880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(result_register()); 177980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallStub(&stub); 178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 17810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 1782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 1794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 18070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 18080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(var, Token::ASSIGN); 1809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Preserve value. 18130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, eax); 1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(eax); // Restore value. 1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, prop->key()->AsLiteral()->handle()); 1817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 18180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Preserve value. 18230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 18240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 1825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ecx, eax); 1826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(edx); 1827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(eax); // Restore value. 1828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 18290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1836d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 18370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::Value op) { 1838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand sides that rewrite to explicit property accesses do not reach 1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // here. 18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 18410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(var->is_global() || var->AsSlot() != NULL); 1842d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1844d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in eax, variable name in 1847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // ecx, and the global object on the stack. 18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ecx, var->name()); 18498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(edx, GlobalObjectOperand()); 18503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 18510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 1854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment for non-const variables and for initialization 1855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // of const variables. Const assignments are simply skipped. 1856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 18570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = var->AsSlot(); 1858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Slot::LOCAL: 1861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, Operand(ebp, SlotOffset(slot))); 1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(edx, Factory::the_hole_value()); 1865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment. 1868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(Operand(ebp, SlotOffset(slot)), eax); 1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, ecx); 1873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, target); 1876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(edx, Factory::the_hole_value()); 1877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 1878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment and issue the write barrier. 1880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(target, eax); 1881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The value of the assignment is in eax. RecordWrite clobbers its 1882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // register arguments. 1883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, eax); 1884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(ecx, offset, edx, ebx); 1886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 18873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call the runtime for the assignment. The runtime will ignore 1891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // const reinitialization. 1892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Value. 1893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(esi); // Context. 1894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 1895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime will ignore const redeclaration. 1897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 19023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 19043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 19073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 19083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 19093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 19153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1921e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Operand(esp, kPointerSize)); // Receiver is now under value. 1922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ecx, prop->key()->AsLiteral()->handle()); 19294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (expr->ends_initialization_block()) { 19304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(edx, Operand(esp, 0)); 19314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 19324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(edx); 19334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(eax); // Result of assignment, saved even if not needed. 1940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(esp, kPointerSize)); // Receiver is under value. 1941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(eax); 19430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, eax); 19444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 19450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 1946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1950d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(Operand(esp, 2 * kPointerSize)); 1960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 19646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 19656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (expr->ends_initialization_block()) { 19666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. 19676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 19686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 19696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1971e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1972d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 19730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 19776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 1978d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(eax); // Result of assignment, saved even if not needed. 19796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1981d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(eax); 1982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 1985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1988d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1991d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 19930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->obj()); 1994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 1995d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 19960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->obj()); 19970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->key()); 1998402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(edx); 1999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 2000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 20010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2005d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 2006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Object> name, 2007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 2008d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 2009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 20103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 20113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 20123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 20133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 20143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 20153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ Set(ecx, Immediate(name)); 20163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source position of the IC call. 20183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(expr->position(), FORCED_POSITION); 2019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 20208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); 20210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 2022d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 20240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2026d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 20287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 20297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Expression* key, 20307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch RelocInfo::Mode mode) { 20318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the key. 20328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(key); 20338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Swap the name of the function and the receiver on the stack to follow 20358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // the calling convention for call ICs. 20368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(ecx); 20378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(eax); 20388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(ecx); 20398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the arguments. 20417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 20427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int arg_count = args->length(); 20433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 20443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 20453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 20463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 20477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 20487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Record source position of the IC call. 20493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(expr->position(), FORCED_POSITION); 20507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 20518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); 20528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. 20530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 20547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Restore context register. 20557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 20568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang context()->DropAndPlug(1, eax); // Drop the key still on the stack. 20577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 20587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 20597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2060d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 2061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 2062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 20643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 20653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 20663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 20673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 20703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(expr->position(), FORCED_POSITION); 2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 2073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 20743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 20753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 20760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, eax); 2077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2080d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 2081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 2082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 2083d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 2084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2085d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // resolve the function we need to call and the receiver of the 2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. Then we call the resolved function using the given 2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 20923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope pos_scope(masm()->positions_recorder()); 20933e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(fun); 20943e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Reserved receiver slot. 20953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(Immediate(Factory::undefined_value())); 2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push the arguments. 20983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 20993e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 21003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push copy of the function - found below the arguments. 21033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(Operand(esp, (arg_count + 1) * kPointerSize)); 2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21053e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push copy of the first argument or undefined if it doesn't exist. 21063e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (arg_count > 0) { 21073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(Operand(esp, arg_count * kPointerSize)); 21083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 21093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(Immediate(Factory::undefined_value())); 21103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push the receiver of the enclosing function and do runtime call. 21133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); 21143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // The runtime call returns a pair of values in eax (function) and 21173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // edx (receiver). Touch up the stack with the right values. 21183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); 21193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); 21203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 21223e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(expr->position(), FORCED_POSITION); 2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 21280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, eax); 2129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 2130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Push global object as receiver for the call IC. 21318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(GlobalObjectOperand()); 2132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 21330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (var != NULL && var->AsSlot() != NULL && 21340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot()->type() == Slot::LOOKUP) { 213559151504615d929945dc59db37bf1166937748c6Steve Block // Call to a lookup slot (dynamically introduced variable). 213659151504615d929945dc59db37bf1166937748c6Steve Block Label slow, done; 213759151504615d929945dc59db37bf1166937748c6Steve Block 21383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 21393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Generate code for loading from variables potentially shadowed 21403e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // by eval-introduced variables. 21413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu EmitDynamicLoadFromSlotFastCase(var->AsSlot(), 21423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu NOT_INSIDE_TYPEOF, 21433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu &slow, 21443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu &done); 21453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 214659151504615d929945dc59db37bf1166937748c6Steve Block 214759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 214859151504615d929945dc59db37bf1166937748c6Steve Block // Call the runtime to find the function to call (returned in eax) 214959151504615d929945dc59db37bf1166937748c6Steve Block // and the object holding it (returned in edx). 2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); // Function. 2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(edx); // Receiver. 215559151504615d929945dc59db37bf1166937748c6Steve Block 215659151504615d929945dc59db37bf1166937748c6Steve Block // If fast case code has been generated, emit code to push the 215759151504615d929945dc59db37bf1166937748c6Steve Block // function and receiver and have the slow path jump around this 215859151504615d929945dc59db37bf1166937748c6Steve Block // code. 215959151504615d929945dc59db37bf1166937748c6Steve Block if (done.is_linked()) { 216059151504615d929945dc59db37bf1166937748c6Steve Block Label call; 216159151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(&call); 216259151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 216359151504615d929945dc59db37bf1166937748c6Steve Block // Push function. 216459151504615d929945dc59db37bf1166937748c6Steve Block __ push(eax); 216559151504615d929945dc59db37bf1166937748c6Steve Block // Push global receiver. 21668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ebx, GlobalObjectOperand()); 216759151504615d929945dc59db37bf1166937748c6Steve Block __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 216859151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&call); 216959151504615d929945dc59db37bf1166937748c6Steve Block } 217059151504615d929945dc59db37bf1166937748c6Steve Block 2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitCallWithStub(expr); 2172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 2173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 2174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 2175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 2176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 2177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 21780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 2179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 21817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call to a keyed property. 21827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // For a synthetic property use keyed load IC followed by function call, 21830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // for a regular property use keyed EmitCallIC. 21843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 21853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(prop->obj()); 21863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2187402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (prop->is_synthetic()) { 21883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 21893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForAccumulatorValue(prop->key()); 21903e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 21917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Record source code position for IC call. 21923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(prop->position(), FORCED_POSITION); 2193402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(edx); // We do not need to keep the receiver. 2194402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 21957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 21960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 2197402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push result (function). 2198402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 2199402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push Global receiver. 22008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ecx, GlobalObjectOperand()); 2201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); 22027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitCallWithStub(expr); 2203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 22047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 2205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 22073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 2209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 2210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // also use the full code generator. 2211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 2212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 2213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 2214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 2215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 2216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 22173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 22183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(fun); 22193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 22218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ebx, GlobalObjectOperand()); 2222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 2223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 2224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 22253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 22263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 22273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 22283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 2230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 2231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 2232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 2233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 2234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 223580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 223680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 223780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 22380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->expression()); 2239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 2241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 22440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 2245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 2248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 2249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 2250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 225180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into edi and eax. 2252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(eax, Immediate(arg_count)); 225380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(edi, Operand(esp, arg_count * kPointerSize)); 2254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 2256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 22570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 226980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 22700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 22710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 227480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(zero, if_true, if_false, fall_through); 2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 228880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 22890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 22900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 229380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(zero, if_true, if_false, fall_through); 2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 230780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 23080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 23090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_false); 2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Factory::null_value()); 2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); 2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_false); 2320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, if_false); 2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(ecx, LAST_JS_OBJECT_TYPE); 232480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(below_equal, if_true, if_false, fall_through); 2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 23313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(args->length() == 1); 23323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 23330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 23343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 23353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 23363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 23373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 233880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 23390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 23400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 23413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 23423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ test(eax, Immediate(kSmiTagMask)); 23433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ j(equal, if_false); 23443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx); 234580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(above_equal, if_true, if_false, fall_through); 23463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 23470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 23483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 23493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 23503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 235980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 23600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 23610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_false); 2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(ebx, Immediate(1 << Map::kIsUndetectable)); 236880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 2369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2374756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2375756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ZoneList<Expression*>* args) { 2376756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ASSERT(args->length() == 1); 2377756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 23780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2379756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2380756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label materialize_true, materialize_false; 2381756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_true = NULL; 2382756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_false = NULL; 238380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 23840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 23850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2386756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2387756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only 2388756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // used in a few functions in runtime.js which should not normally be hit by 2389756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // this compiler. 2390756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ jmp(if_false); 23910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2392756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2393756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2394756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 240380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 24040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 24050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_false); 2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 241080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 242480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 24250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 24260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_false); 2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 243180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 244580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 24460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 24470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_false); 2451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); 245280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 246580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 24660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 24670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(Operand(eax, StandardFrameConstants::kContextOffset), 2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &check_frame_marker); 2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset)); 2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset), 2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); 248380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 24930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 24940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 249980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(ebx); 2504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(eax, Operand(ebx)); 250580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ArgumentsAccessStub expects the key in edx and the formal 2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // parameter count in eax. 25160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, eax); 2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); 2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 25210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label exit; 2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); 2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), 2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &exit); 2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (FLAG_debug_code) __ AbortIfNotSmi(eax); 25440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, &null); 2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, eax); // Map is now in eax. 2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, &null); 2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // As long as JS_FUNCTION_TYPE is the last instance type and it is 2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // LAST_JS_OBJECT_TYPE. 2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 25688defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ CmpInstanceType(eax, JS_FUNCTION_TYPE); 2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &function); 2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the constructor in the map is a function. 2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, Map::kConstructorOffset)); 2573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &non_function_constructor); 2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // eax now contains the constructor function. Grab the 2577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); 2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset)); 2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::function_class_symbol()); 2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::Object_symbol()); 2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::null_value()); 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING 2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 26140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 26150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif 2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::undefined_value()); 26210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); 2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 26353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Allocate a heap number. 26363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edi, eax); 2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(0, ebx); 2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction(ExternalReference::random_uint32_function(), 0); 2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in eax to 0.(32 random bits) in a double 2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is implemented on both SSE2 and FPU. 2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CpuFeatures::IsSupported(SSE2)) { 2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CpuFeatures::Scope fscope(SSE2); 2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm1, Operand(ebx)); 2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movd(xmm0, Operand(eax)); 2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cvtss2sd(xmm1, xmm1); 2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pxor(xmm0, xmm1); 2655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ subsd(xmm0, xmm1); 2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); 2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x4130000000000000 is 1.0 x 2^20 as a double. 2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(FieldOperand(edi, HeapNumber::kExponentOffset), 2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(0x41300000)); 2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), eax); 2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0)); 2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ fsubp(1); 2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, edi); 26690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 26770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 26780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 26790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 26810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 26890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 26900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 26910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 26920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(3)); 2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 26940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); // Load the object. 2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done; 2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, &done); 2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); 2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 27130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 27200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 27210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_pow, 2); 27230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Load the object. 27310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); // Load the value. 2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(ebx); // eax = value. ebx = object. 2733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel done; 2735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 2736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ test(ebx, Immediate(kSmiTagMask)); 2737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, &done); 2738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 2740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); 2741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 2742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 2744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); 2745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 2747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(edx, eax); 2748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx); 2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 27510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 27590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 27630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 27737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(eax, ebx); 27747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 27787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 27810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(ebx); 2782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 27867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 27877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 27890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 27907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = ebx; 27927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = eax; 27937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = ecx; 27947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = edx; 27957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 27977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 27997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 28007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 28017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 28027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 28037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch, 28047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 28057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 28067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 28077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 28087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 28097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 28107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 28117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 28137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 28147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 28157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(result, Immediate(Factory::nan_value())); 28167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 28177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 2819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move the undefined value into the result register, which will 28207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 28217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(result, Immediate(Factory::undefined_value())); 28227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 28237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 28257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 28267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 28280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 28337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 28347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 28360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 28377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = ebx; 28397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = eax; 28407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = ecx; 28417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = edx; 28427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 28437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 28457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 28477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 28487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 28497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 28507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 28517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 28527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 28537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 28547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 28557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 28567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 28577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 28587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 28597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 28607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 28627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 28637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 28647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(result, Immediate(Factory::empty_string())); 28657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 28667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 28687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 28697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 28707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(result, Immediate(Smi::FromInt(0))); 28717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 28727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 28747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 28757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 28770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 28787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 28797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 28850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 2888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 28890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 28970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 2900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 29010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke TranscendentalCacheStub stub(TranscendentalCache::SIN); 2908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 29090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 29110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke TranscendentalCacheStub stub(TranscendentalCache::COS); 2918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 29190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 29210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime function. 2927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 29280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sqrt, 1); 29300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 2936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length() - 2; // For receiver and function. 29380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Receiver. 2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 29400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i + 1)); 2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 29420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(arg_count + 1)); // Function. 2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // InvokeFunction requires function in edi. Move it in there. 2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!result_register().is(edi)) __ mov(edi, result_register()); 2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeFunction(edi, count, CALL_FUNCTION); 2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 29490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 29550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 29560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 29570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kRegExpConstructResult, 3); 29590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 29650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 29660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 29670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kSwapElements, 3); 29690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 2974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 2977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 2980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Top::global_context()->jsfunction_result_caches()); 2981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 2982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 2983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, Factory::undefined_value()); 29840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 2985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = eax; 2991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = ebx; 2992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register tmp = ecx; 299359151504615d929945dc59db37bf1166937748c6Steve Block __ mov(cache, ContextOperand(esi, Context::GLOBAL_INDEX)); 2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(cache, 2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, GlobalObject::kGlobalContextOffset)); 299659151504615d929945dc59db37bf1166937748c6Steve Block __ mov(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 2997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(cache, 2998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, not_found; 3001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 3002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp)); 3005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, ¬_found); 3006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1)); 3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 3009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 3011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(cache); 3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(key); 3014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 30170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 3018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3021bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 3022bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT_EQ(2, args->length()); 3023bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3024bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register right = eax; 3025bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register left = ebx; 3026bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp = ecx; 3027bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 30280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 30290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3030bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(left); 3031bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3032bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label done, fail, ok; 3033bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(left, Operand(right)); 3034bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(equal, &ok); 3035bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Fail if either is a non-HeapObject. 3036bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(tmp, left); 3037bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ and_(Operand(tmp), right); 3038bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ test(Operand(tmp), Immediate(kSmiTagMask)); 3039bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(zero, &fail); 3040bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CmpObjectType(left, JS_REGEXP_TYPE, tmp); 3041bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &fail); 3042bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset)); 3043bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(not_equal, &fail); 3044bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); 3045bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); 3046bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(equal, &ok); 3047bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&fail); 3048bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(eax, Immediate(Factory::false_value())); 3049bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&done); 3050bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&ok); 3051bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(eax, Immediate(Factory::true_value())); 3052bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&done); 3053bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 30540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 3055bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 3056bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3057bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 305880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { 305980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(args->length() == 1); 306080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 30610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 306280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 306380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (FLAG_debug_code) { 306480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ AbortIfNotString(eax); 306580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 306680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 306780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 306880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 306980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 307080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 30710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 30720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 307380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 307480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(FieldOperand(eax, String::kHashFieldOffset), 307580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(String::kContainsCachedArrayIndexMask)); 307680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(zero, if_true, if_false, fall_through); 307780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 30780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 307980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 308080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 308180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 308280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 308380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(args->length() == 1); 308480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 30850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 308680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 308780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (FLAG_debug_code) { 308880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ AbortIfNotString(eax); 308980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 309080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 309180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); 309280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(eax, eax); 309380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 30940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 309580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 309680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 309780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 30988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 30998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label bailout; 31008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label done; 31018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(args->length() == 2); 31038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We will leave the separator on the stack until the end of the function. 31048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForStackValue(args->at(1)); 31058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load this to eax (= array) 31068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(args->at(0)); 31078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // All aliases of the same register have disjoint lifetimes. 31098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register array = eax; 31108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register result_pos = no_reg; 31118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register index = edi; 31138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register current_string_length = ecx; // Will be ecx when live. 31158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register current_string = edx; 31178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register scratch = ebx; 31198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register scratch_2 = esi; 31218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register new_padding_chars = scratch_2; 31228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand separator = Operand(esp, 4 * kPointerSize); // Already pushed. 31248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand elements = Operand(esp, 3 * kPointerSize); 31258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand result = Operand(esp, 2 * kPointerSize); 31268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand padding_chars = Operand(esp, 1 * kPointerSize); 31278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand array_length = Operand(esp, 0); 31288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(Operand(esp), Immediate(4 * kPointerSize)); 31298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check that eax is a JSArray 31328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ test(array, Immediate(kSmiTagMask)); 31338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(zero, &bailout); 31348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 31358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(not_equal, &bailout); 31368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check that the array has fast elements. 31388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ test_b(FieldOperand(scratch, Map::kBitField2Offset), 31398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1 << Map::kHasFastElements); 31408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(zero, &bailout); 31418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the array is empty, return the empty string. 31438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset)); 31448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sar(scratch, 1); 31458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label non_trivial; 31468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(not_zero, &non_trivial); 31478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(result, Factory::empty_string()); 31488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ jmp(&done); 31498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&non_trivial); 31518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(array_length, scratch); 31528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset)); 31548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(elements, scratch); 31558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // End of array's live range. 31578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang result_pos = array; 31588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang array = no_reg; 31598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check that the separator is a flat ascii string. 31628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(current_string, separator); 31638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ test(current_string, Immediate(kSmiTagMask)); 31648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(zero, &bailout); 31658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 31668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 31678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ and_(scratch, Immediate( 31688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 31698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 31708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(not_equal, &bailout); 31718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the separator is the empty string, replace it with NULL. 31728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // The test for NULL is quicker than the empty string test, in a loop. 31738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset), 31748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Immediate(0)); 31758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label separator_checked; 31768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(not_zero, &separator_checked); 31778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(separator, Immediate(0)); 31788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&separator_checked); 31798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check that elements[0] is a flat ascii string, and copy it in new space. 31818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch, elements); 31828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(current_string, FieldOperand(scratch, FixedArray::kHeaderSize)); 31838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ test(current_string, Immediate(kSmiTagMask)); 31848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(zero, &bailout); 31858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 31868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 31878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ and_(scratch, Immediate( 31888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 31898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 31908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(not_equal, &bailout); 31918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Allocate space to copy it. Round up the size to the alignment granularity. 31938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(current_string_length, 31948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FieldOperand(current_string, String::kLengthOffset)); 31958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ shr(current_string_length, 1); 31968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 31978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Live registers and stack values: 31988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // current_string_length: length of elements[0]. 31998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // New string result in new space = elements[0] 32018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ AllocateAsciiString(result_pos, current_string_length, scratch_2, 32028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang index, no_reg, &bailout); 32038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(result, result_pos); 32048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Adjust current_string_length to include padding bytes at end of string. 32068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Keep track of the number of padding bytes. 32078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(new_padding_chars, current_string_length); 32088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask)); 32098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask)); 32108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(new_padding_chars, Operand(current_string_length)); 32118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ neg(new_padding_chars); 32128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(padding_chars, new_padding_chars); 32138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label copy_loop_1_done; 32158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label copy_loop_1; 32168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ test(current_string_length, Operand(current_string_length)); 32178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(zero, ©_loop_1_done); 32188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(©_loop_1); 32198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(Operand(current_string_length), Immediate(kPointerSize)); 32208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch, FieldOperand(current_string, current_string_length, 32218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang times_1, SeqAsciiString::kHeaderSize)); 32228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(FieldOperand(result_pos, current_string_length, 32238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang times_1, SeqAsciiString::kHeaderSize), 32248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang scratch); 32258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(not_zero, ©_loop_1); 32268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(©_loop_1_done); 32278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(index, Immediate(1)); 32298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Loop condition: while (index < length). 32308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label loop; 32318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&loop); 32328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(index, array_length); 32338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(greater_equal, &done); 32348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the separator is the empty string, signalled by NULL, skip it. 32368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label separator_done; 32378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(current_string, separator); 32388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ test(current_string, Operand(current_string)); 32398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(zero, &separator_done); 32408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Append separator to result. It is known to be a flat ascii string. 32428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ AppendStringToTopOfNewSpace(current_string, current_string_length, 32438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang result_pos, scratch, scratch_2, result, 32448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang padding_chars, &bailout); 32458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&separator_done); 32468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Add next element of array to the end of the result. 32488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get current_string = array[index]. 32498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch, elements); 32508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(current_string, FieldOperand(scratch, index, 32518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang times_pointer_size, 32528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FixedArray::kHeaderSize)); 32538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If current != flat ascii string drop result, return undefined. 32548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ test(current_string, Immediate(kSmiTagMask)); 32558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(zero, &bailout); 32568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 32578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 32588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ and_(scratch, Immediate( 32598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 32608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 32618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ j(not_equal, &bailout); 32628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Append current to the result. 32648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ AppendStringToTopOfNewSpace(current_string, current_string_length, 32658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang result_pos, scratch, scratch_2, result, 32668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang padding_chars, &bailout); 32678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(Operand(index), Immediate(1)); 32688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ jmp(&loop); // End while (index < length). 32698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&bailout); 32718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(result, Factory::undefined_value()); 32728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&done); 32738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(eax, result); 32748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Drop temp values from the stack, and restore context register. 32758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(Operand(esp), Immediate(5 * kPointerSize)); 32768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 32788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang context()->Plug(eax); 32798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 32808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 32818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 3282d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 3284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 3285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 3286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 3287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 32913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 32923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 3294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 32958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(eax, GlobalObjectOperand()); 3296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); 3297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 32983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 32993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 33003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 33013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 33020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 3303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 3306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the JS runtime function via a call IC. 3307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Set(ecx, Immediate(expr->name())); 3308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 33098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); 33100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 33110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Restore context register. 3312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 3314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the C runtime function. 3315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 3316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 33170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 3318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 3324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->expression()->AsProperty(); 3326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 3327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop == NULL && var == NULL) { 3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-property, non-variable reference is true. 3329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression may have side effects. 3330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 33310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(true); 3332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var != NULL && 3333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke !var->is_global() && 33340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot() != NULL && 33350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot()->type() != Slot::LOOKUP) { 3336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-global, non-dynamic variables is false. 3337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression does not have side effects. 33380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(false); 3339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 3340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Property or variable reference. Call the delete builtin with 3341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object and property name as arguments. 3342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 33430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 33440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->key()); 3345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->is_global()) { 33468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(GlobalObjectOperand()); 3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 3348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 3349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-global variable. Call the runtime to look up the context 3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // where the variable was introduced. 3351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 3352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 3353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLookupContext, 2); 3354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(eax); 3355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(Immediate(var->name())); 3356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 3359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 3361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 3364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 3365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 33660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Factory::undefined_value()); 3367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 33683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 3371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 337280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 337680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 3377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Notice that the labels are swapped. 33780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 33790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_false, &if_true, &fall_through); 338080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VisitForControl(expr->expression(), if_true, if_false, fall_through); 33810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_false, if_true); // Labels swapped. 3382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 3386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 33870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { StackValueContext context(this); 33880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 33890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 33910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 3392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 3396d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 33970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 3398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 3399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ test(result_register(), Immediate(kSmiTagMask)); 3400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(zero, &no_conversion); 3401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(result_register()); 3402d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3403d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 34040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result_register()); 3405d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 3406d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3407d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 34084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 34094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 341080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 3411ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke UnaryOverwriteMode overwrite = 3412ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 34130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenericUnaryOpStub stub(Token::SUB, overwrite, NO_UNARY_FLAGS); 34144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 34154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register eax. 34160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 34174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 34180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 34194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 34204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 34214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 34224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 34234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 342480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The generic unary operation stub expects the argument to be 342580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // in the accumulator register eax. 34260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 342780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label done; 34280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_case = ShouldInlineSmiCase(expr->op()); 34290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_case) { 34300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel call_stub; 343180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 343280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, &call_stub); 343380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ lea(eax, Operand(eax, kSmiTagMask)); 343480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ not_(eax); 343580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(&done); 343680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&call_stub); 343780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 343880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool overwrite = expr->expression()->ResultOverwriteAllowed(); 343980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UnaryOverwriteMode mode = 344080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 34410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen UnaryOpFlags flags = inline_smi_case 34420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_UNARY_SMI_CODE_IN_STUB 34430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_UNARY_FLAGS; 34440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags); 34454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 34464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 34470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 34484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 34494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 34504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 3451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 34533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3457d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 3458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CountOperation"); 345980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 346080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 3462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // as the left-hand side. 3463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 3464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 3465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 3469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 3470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 3472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 3473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 3474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 3475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 3476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 3477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 3481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 3482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 34830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 34840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 3485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 3486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 34870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 3488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(Immediate(Smi::FromInt(0))); 3489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 3491402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Put the object both on the stack and in the accumulator. 34920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 3493402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 3494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 3495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 34960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 34970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 3498402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edx, Operand(esp, 0)); 3499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 3500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 3501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3504d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 35050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel no_conversion; 350680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(expr->op())) { 350780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 350880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, &no_conversion); 350980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 3510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(eax); 3511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 35133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 3515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 35160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 35170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 35180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 35190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 35200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 35210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 35220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(eax); 35230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 35240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 35250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(Operand(esp, kPointerSize), eax); 35260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 35270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 35280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(Operand(esp, 2 * kPointerSize), eax); 35290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 35300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 35350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel stub_call; 35360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 353780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(expr->op())) { 3538d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 3539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3540d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 3541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3543d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(overflow, &stub_call); 3544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 3545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 3546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ test(eax, Immediate(kSmiTagMask)); 3547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ j(zero, &done); 3548d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 3549d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 3550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (expr->op() == Token::INC) { 3551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 3553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3554d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3555d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 3557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenericBinaryOpStub stub(expr->binary_op(), 3558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NO_OVERWRITE, 35596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NO_GENERIC_BINARY_FLAGS, 35606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block TypeInfo::Unknown()); 3561d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke stub.GenerateCall(masm(), eax, Smi::FromInt(1)); 3562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 3563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in eax. 3565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 3566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 3567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 3568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 35690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 35700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 35710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 35720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 35730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For all contexts except EffectContext We have the result on 3574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 35750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 35760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 3580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 35810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 3582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 3585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ecx, prop->key()->AsLiteral()->handle()); 35864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ pop(edx); 3587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 35880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 3589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 35900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 35910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 35940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 3595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 35996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 36006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 3601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 36020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 3603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 36046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Result is on the stack 36050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 36060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 36090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 3610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 36133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 36143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 36153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 36163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 36170d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 361880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VariableProxy* proxy = expr->AsVariableProxy(); 36190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsEffect()); 36200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsTest()); 36210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 362280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 362380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Comment cmnt(masm_, "Global variable"); 36248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(eax, GlobalObjectOperand()); 362580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(ecx, Immediate(proxy->name())); 362680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 362780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Use a regular load, not a contextual load, to avoid a reference 362880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // error. 36290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 36300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 363180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (proxy != NULL && 36320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen proxy->var()->AsSlot() != NULL && 36330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 363459151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 363559151504615d929945dc59db37bf1166937748c6Steve Block 363659151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 363759151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 36380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = proxy->var()->AsSlot(); 363959151504615d929945dc59db37bf1166937748c6Steve Block EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 364059151504615d929945dc59db37bf1166937748c6Steve Block 364159151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 364280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(esi); 364380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(Immediate(proxy->name())); 364480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 364559151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 364659151504615d929945dc59db37bf1166937748c6Steve Block 36470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 364880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 364980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // This expression cannot throw a reference error at the top level. 36500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Visit(expr); 3651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 36533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 36543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 365580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::TryLiteralCompare(Token::Value op, 365680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 365780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right, 365880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 365980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 366080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 366180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (op != Token::EQ && op != Token::EQ_STRICT) return false; 366280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 366380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for the pattern: typeof <expression> == <string literal>. 366480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Literal* right_literal = right->AsLiteral(); 366580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (right_literal == NULL) return false; 366680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<Object> right_literal_value = right_literal->handle(); 366780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (!right_literal_value->IsString()) return false; 366880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UnaryOperation* left_unary = left->AsUnaryOperation(); 366980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 367080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<String> check = Handle<String>::cast(right_literal_value); 367180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 36720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 36730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(left_unary->expression()); 36740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 36750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 367680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (check->Equals(Heap::number_symbol())) { 367780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 367880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, if_true); 367980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 368080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Factory::heap_number_map()); 368180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 368280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::string_symbol())) { 368380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 368480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, if_false); 368580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 368680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 368780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 368880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 368980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, if_false); 369080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE); 369180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(below, if_true, if_false, fall_through); 369280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::boolean_symbol())) { 369380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(eax, Factory::true_value()); 3694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 369580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(eax, Factory::false_value()); 369680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 369780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::undefined_symbol())) { 369880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(eax, Factory::undefined_value()); 3699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 370080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 370180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, if_false); 370280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 370380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 370480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 370580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 370680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 370780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::function_symbol())) { 370880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 370980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, if_false); 371080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx); 3711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 371280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Regular expressions => 'function' (they are callable). 371380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpInstanceType(edx, JS_REGEXP_TYPE); 371480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 371580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::object_symbol())) { 371680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 3717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(zero, if_false); 371880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(eax, Factory::null_value()); 371980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 372080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Regular expressions => 'function', not 'object'. 372180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CmpObjectType(eax, JS_REGEXP_TYPE, edx); 372280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_false); 372380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 372480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 372580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 372680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, if_false); 372780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for JS objects => true. 372880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); 372980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 373080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(less, if_false); 373180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(ecx, LAST_JS_OBJECT_TYPE); 373280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(less_equal, if_true, if_false, fall_through); 373380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 373480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 3735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 373680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 373780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return true; 3738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 374380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 3744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 3746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 3747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 375180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 37520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 37530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 375480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 375580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // First we try a fast inlined version of the compare when one of 375680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // the operands is a literal. 375780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->op(); 375880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left = expr->left(); 375980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right = expr->right(); 376080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { 37610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 376280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return; 376380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 3764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 37650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 3766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 37680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 3769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(eax, Factory::true_value()); 377180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 3772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 37733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 37750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 3776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 3777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ test(eax, Operand(eax)); 377980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns 0 for true. 378080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(zero, if_true, if_false, fall_through); 3781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 37850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 3786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = no_condition; 3787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 378880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 3789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 3790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 3791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through 379280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::EQ: 3793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = equal; 3794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(edx); 3795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 3797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 3798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(edx); 3799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 3801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 3802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = less; 3803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edx, result_register()); 3804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(eax); 3805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 3807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Reverse left and right sizes to obtain ECMA-262 conversion order. 3808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 3809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edx, result_register()); 3810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(eax); 3811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 3813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = greater_equal; 3814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(edx); 3815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 3817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 3818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 3820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 38220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 38230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 38240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NearLabel slow_case; 382580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(ecx, Operand(edx)); 382680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ or_(ecx, Operand(eax)); 382780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(ecx, Immediate(kSmiTagMask)); 382880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_zero, &slow_case, not_taken); 382980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(edx, Operand(eax)); 383080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, NULL); 383180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 383280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 3833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 38340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareFlags flags = inline_smi_code 38350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_SMI_COMPARE_IN_STUB 38360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_COMPARE_FLAGS; 38370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareStub stub(cc, strict, flags); 3838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ test(eax, Operand(eax)); 384080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, fall_through); 3841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 38423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 38433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 3845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 38460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 385080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 385180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 385280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 385380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 385480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 38550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 38560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 385780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 38580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 385980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(eax, Factory::null_value()); 386080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (expr->is_strict()) { 386180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 386280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 386380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 386480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(eax, Factory::undefined_value()); 386580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(equal, if_true); 386680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(eax, Immediate(kSmiTagMask)); 386780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, if_false); 386880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // It can be an undetectable object. 386980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 387080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset)); 387180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ test(edx, Immediate(1 << Map::kIsUndetectable)); 387280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 387380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 38740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 387580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 387680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 387780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 3879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 38800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(eax); 38810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 38820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 38830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 38840d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 38850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return eax; 3886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 38890d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 38900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return esi; 38910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 38940d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { 38950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(mode == RelocInfo::CODE_TARGET || 38960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mode == RelocInfo::CODE_TARGET_CONTEXT); 38970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ call(ic, mode); 38980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 38990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // If we're calling a (keyed) load or store stub, we have to mark 39000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // the call as containing no inlined code so we will not attempt to 39010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // patch it. 39020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (ic->kind()) { 39030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case Code::LOAD_IC: 39040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case Code::KEYED_LOAD_IC: 39050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case Code::STORE_IC: 39060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case Code::KEYED_STORE_IC: 39070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ nop(); // Signals no inlined code. 39080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 39090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen default: 39100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Do nothing. 39110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 39120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 39130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3916d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 3918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(ebp, frame_offset), value); 39193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 39203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 39213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3922d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 392359151504615d929945dc59db37bf1166937748c6Steve Block __ mov(dst, ContextOperand(esi, context_index)); 3924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 3928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 3929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3930d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 3931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address on top of stack (smi encoded Code* delta) 3932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(edx)); 3933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edx, Operand(esp, 0)); 3934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(Operand(edx), Immediate(masm_->CodeObject())); 3935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 3936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 3937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(edx, Operand(edx)); // Convert to smi. 3938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(esp, 0), edx); 3939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 3940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 3941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3944d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 3945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(edx)); 3946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 3947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 3948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address. 3949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edx, Operand(esp, 0)); 3950e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sar(edx, 1); // Convert smi to int. 3951e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(Operand(edx), Immediate(masm_->CodeObject())); 3952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(Operand(esp, 0), edx); 3953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // And return. 3954e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 3955e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3957e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __ 3959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 39603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 3961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 3963