full-codegen-arm.cc revision 8a31eba00023874d4a1dcdc5f411cc4336776874
13ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Copyright 2009 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_ARM) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h" 333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h" 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h" 35d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#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. The actual 483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the 493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function. 503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o r1: the JS function object being called (ie, ourselves) 533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o cp: our context 543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o fp: our caller's frame pointer 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o sp: stack pointer 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o lr: return address 573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout. 60756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::Generate(CompilationInfo* info) { 613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(info_ == NULL); 623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu info_ = info; 633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 66f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG 67f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (strlen(FLAG_stop_at) > 0 && 68f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 69f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ stop("stop-at"); 70f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 71f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif 72f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int locals_count = scope()->num_stack_slots(); 743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ Push(lr, fp, cp, r1); 76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (locals_count > 0) { 77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load undefined value here, so the value is ready for the loop 78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // below. 79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Adjust fp to point to caller's fp. 82756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ add(fp, sp, Operand(2 * kPointerSize)); 833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 84756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 85756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < locals_count; i++) { 86756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(ip); 874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 88756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 89d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 90756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bool function_in_register = true; 914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 92756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots > 0) { 95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate local context"); 96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Argument to NewContext is the function, which is in r1. 97756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(r1); 98756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots <= FastNewContextStub::kMaximumSlots) { 99756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastNewContextStub stub(heap_slots); 100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallRuntime(Runtime::kNewContext, 1); 103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick function_in_register = false; 105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Context is returned in both r0 and cp. It replaces the context 106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // passed to us. It's saved in the stack and kept live in cp. 107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 108756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy any necessary parameters into the context. 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 __ ldr(r0, MemOperand(fp, parameter_offset)); 117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r1, Operand(Context::SlotOffset(slot->index()))); 119756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ str(r0, MemOperand(cp, r1)); 120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Update the write barrier. This clobbers all involved 121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // registers, so we have to use two more registers to avoid 122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // clobbering cp. 123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r2, Operand(cp)); 124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ RecordWrite(r2, Operand(r1), r3, r0); 125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 128d0582a6c46733687d045e4188a1bcd0123c758a1Steve 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 // Load this again, if it's used by the local context below. 135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 137756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r3, r1); 138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Receiver is just before the parameters on the caller's stack. 140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int offset = scope()->num_parameters() * kPointerSize; 141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ add(r2, fp, 142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Operand(StandardFrameConstants::kCallerSPOffset + offset)); 143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters()))); 144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ Push(r3, r2, r1); 145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments to ArgumentsAccessStub: 147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // function, receiver address, parameter count. 148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The stub will rewrite receiever and parameter count if the previous 149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // stack frame was an arguments adapter frame. 150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 152756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Duplicate the value; move-to-slot operation might clobber registers. 153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r3, r0); 1540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Move(arguments->AsSlot(), r0, r1, r2); 1550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); 156756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Move(dot_arguments_slot, r3, r1, r2); 157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke { Comment cmnt(masm_, "[ Declarations"); 160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // For named function expressions, declare the function name as a 161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant. 162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && scope()->function() != NULL) { 163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(scope()->function(), Variable::CONST, NULL); 164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Visit all the explicit declarations unless there is an illegal 166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // redeclaration. 167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->HasIllegalRedeclaration()) { 168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke scope()->VisitIllegalRedeclaration(this); 169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitDeclarations(scope()->declarations()); 171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check the stack for overflow or break request. 175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block { Comment cmnt(masm_, "[ Stack check"); 1764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ LoadRoot(r2, Heap::kStackLimitRootIndex); 1774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(sp, Operand(r2)); 1784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke StackCheckStub stub; 1798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ip, 1804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()), 1814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke RelocInfo::CODE_TARGET), 1824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LeaveCC, 1834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke lo); 1848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Call(ip, lo); 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceEnter, 0); 1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Body"); 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu VisitStatements(function()->body()); 194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 1983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit a 'return undefined' in case control fell off the end of the 1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // body. 2003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ b(&return_label_); 210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the return value on the stack as the parameter. 2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Runtime::TraceExit returns its parameter in r0. 2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 2163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 2173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make sure that the constant pool is not emitted inside of the return 2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // sequence. 2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { Assembler::BlockConstPoolScope block_const_pool(masm_); 2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Here we use masm_-> instead of the __ macro to avoid the code coverage 2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // tool from instrumenting as we rely on the code size here. 2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; 230bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ RecordJSReturn(); 2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->mov(sp, fp); 2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->ldm(ia_w, sp, fp.bit() | lr.bit()); 2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->add(sp, sp, Operand(sp_delta)); 2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->Jump(lr); 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check that the size of the code used for returning matches what is 2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // expected by the debugger. If the sp_delts above cannot be encoded in the 2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // add instruction the add will generate two instructions. 2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int return_sequence_length = 2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->InstructionsGeneratedSince(&check_exit_codesize); 2447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CHECK(return_sequence_length == 2457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Assembler::kJSReturnSequenceInstructions || 2467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return_sequence_length == 2477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Assembler::kJSReturnSequenceInstructions + 1); 2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 25380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenFullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( 25480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, Expression* left, Expression* right) { 25580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(ShouldInlineSmiCase(op)); 25680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return kNoConstants; 25780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 25880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 25980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2600d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Slot* slot) const { 2610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2640d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { 2650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->Move(result_register(), slot); 2660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2690d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { 2700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->Move(result_register(), slot); 2710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2750d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Slot* slot) const { 2760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 2770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->Move(result_register(), slot); 2780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2820d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 2830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 2840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2860d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 2870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 2930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 2940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 2950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 2960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 2970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 3000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (index == Heap::kUndefinedValueRootIndex || 3010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kNullValueRootIndex || 3020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kFalseValueRootIndex) { 3030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(false_label_); 3040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (index == Heap::kTrueValueRootIndex) { 3050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(true_label_); 3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 3080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3130d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 3140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3170d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 3190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 3200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3230d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 3240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Immediates can be pushed directly. 3250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 3260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 3270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3300d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 3310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 3320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 3330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(false_label_); 3340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsTrue() || lit->IsJSObject()) { 3350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(true_label_); 3360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 3370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 3380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(false_label_); 3390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(true_label_); 3410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 3430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 3440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(false_label_); 3450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(true_label_); 3470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 3490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 3500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 3510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3560d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count, 3570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 3590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3630d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 3640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int count, 3650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 3690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3720d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 3730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count > 1) __ Drop(count - 1); 3760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(reg, MemOperand(sp, 0)); 377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3800d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count, 3810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 3820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 3830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 3840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 3850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 3860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen codegen()->DoTest(true_label_, false_label_, fall_through_); 3870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3900d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 3910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 3920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT_EQ(materialize_true, materialize_false); 3930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 3940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 3980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 3990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 4000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 4010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 4020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 4030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 4040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 4050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 4060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4100d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 4110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 4120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 4130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 4140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 4150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kTrueValueRootIndex); 4160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(ip); 4170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 4190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kFalseValueRootIndex); 4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(ip); 4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 4220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(materialize_false == false_label_); 4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(materialize_true == true_label_); 4290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const { 4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4360d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 4380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 4390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), value_root_index); 4400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 4450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, value_root_index); 4470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(ip); 4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4510d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 4520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 4530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ b(true_label_); 4540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 4550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ b(false_label_); 456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 46080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::DoTest(Label* if_true, 46180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 46280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the runtime to find the boolean value of the source and then 464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // translate it into control flow to the pair of labels. 46580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(result_register()); 466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kToBool, 1); 467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(ip, Heap::kTrueValueRootIndex); 468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r0, ip); 46980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 47080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 47380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc, 47480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 47580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 47680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 47780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 47880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(cc, if_true); 47980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 48080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(NegateCondition(cc), if_false); 48180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 48280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(cc, if_true); 48380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(if_false); 484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (slot->type()) { 490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOCAL: 492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return MemOperand(fp, SlotOffset(slot)); 493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::CONTEXT: { 494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int context_chain_length = 4953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->ContextChainLength(slot->var()->scope()); 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadContext(scratch, context_chain_length); 49759151504615d929945dc59db37bf1166937748c6Steve Block return ContextOperand(scratch, slot->index()); 498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOOKUP: 500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return MemOperand(r0, 0); 504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 507d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) { 508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Use destination as scratch. 509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand slot_operand = EmitSlotSearch(source, destination); 510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(destination, slot_operand); 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 514d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst, 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register src, 516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2) { 518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!scratch1.is(src) && !scratch2.is(src)); 520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(dst, scratch1); 521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(src, location); 522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (dst->type() == Slot::CONTEXT) { 5249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(scratch1, 5259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Operand(Context::SlotOffset(dst->index())), 5269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen scratch2, 5279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen src); 528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable, 533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable::Mode mode, 534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FunctionLiteral* function) { 535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(variable != NULL); // Must have been resolved. 5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = variable->AsSlot(); 538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = variable->AsProperty(); 539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(ip, MemOperand(fp, SlotOffset(slot))); 547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), MemOperand(fp, SlotOffset(slot))); 550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 56159151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, ContextOperand(cp, Context::FCONTEXT_INDEX)); 562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r1, cp); 563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(eq, "Unexpected declaration in current context."); 564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 56759151504615d929945dc59db37bf1166937748c6Steve Block __ str(ip, ContextOperand(cp, slot->index())); 568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the_hole_value is in old space. 569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 57159151504615d929945dc59db37bf1166937748c6Steve Block __ str(result_register(), ContextOperand(cp, slot->index())); 572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We know that we have written a function, which is not a smi. 5744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r1, Operand(cp)); 5759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r1, Operand(offset), r2, result_register()); 576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(variable->name())); 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(mode == Variable::VAR || 583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke mode == Variable::CONST); 584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PropertyAttributes attr = 585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke (mode == Variable::VAR) ? NONE : READ_ONLY; 586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r1, Operand(Smi::FromInt(attr))); 587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1, r0); 594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1); 596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Push initial value for function declaration. 5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(function); 598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(Smi::FromInt(0))); // No initial value! 600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1, r0); 601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL || mode == Variable::CONST) { 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 6110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL) { 6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->key()); 6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(function); 615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, result_register()); // Key. 619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); 620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); // Receiver. 622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Value in r0 is ignored (declarations are statements). 626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 6373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 6383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The context is the first argument. 6393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r1, Operand(pairs)); 6403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r1, r0); 6423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 6433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 6443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 0)); // Switch value. 6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 67980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ orr(r2, r1, r0); 68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r2, Operand(kSmiTagMask)); 68180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(ne, &slow_case); 68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, r0); 68380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(ne, &next_test); 68480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 68580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(clause->body_target()->entry_label()); 686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_case); 68780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 68880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 6890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareFlags flags = inline_smi_code 6900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_SMI_COMPARE_IN_STUB 6910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_COMPARE_FLAGS; 6920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareStub stub(eq, true, flags, r1, r0); 693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 6949ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &next_test); 696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(clause->body_target()->entry_label()); 698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(nested_statement.break_target()); 706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(default_clause->body_target()->entry_label()); 708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(clause->body_target()->entry_label()); 715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(nested_statement.break_target()); 719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the object to enumerate over. Both SpiderMonkey and JSC 731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ignore null and undefined in contrast to the specification; see 732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ECMA-262 section 12.6.4. 7330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &exit); 737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kNullValueRootIndex); 738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &exit); 740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &convert); 744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); 745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(hs, &done_convert); 746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); 749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 75259151504615d929945dc59db37bf1166937748c6Steve Block // BUG(867): Check cache validity in generated code. This is a fast 75359151504615d929945dc59db37bf1166937748c6Steve Block // case for the JSObject::IsSimpleEnum cache validity checks. If we 75459151504615d929945dc59db37bf1166937748c6Steve Block // cannot guarantee cache validity, call the runtime system to check 75559151504615d929945dc59db37bf1166937748c6Steve Block // cache validity or get the property names in a fixed array. 756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Duplicate the enumerable object on the stack. 759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label fixed_array; 765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, r0); 766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); 767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kMetaMapRootIndex); 768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, ip); 769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &fixed_array); 770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register r0. Get the enumeration cache from it. 772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, Map::kInstanceDescriptorsOffset)); 773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset)); 774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset)); 775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Setup the four remaining stack slots. 777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Map. 778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset)); 779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push enumeration cache, enumeration cache length (as smi) and zero. 781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r2, r1, r0); 782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register r0. Iterate through that. 785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, Operand(Smi::FromInt(0))); // Map (0) - force slow check. 787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); 788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); 789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); // Fixed array length (as smi) and initial index. 791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the current count to r0, load the length to r1. 795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); 796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); // Compare to the array length. 797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(hs, loop_statement.break_target()); 798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register r3. 800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the expected map from the stack or a zero map in the 805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register r2. 806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); 807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If not, we have to filter the key. 810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label update_each; 811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); 812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); 813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r4, Operand(r2)); 814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &update_each); 815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 816756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Convert the entry to a string or (smi) 0 if it isn't a property 817756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // any more. If the property has been removed while iterating, we 818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); // Enumerable. 820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r3); // Current entry. 821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); 822756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r3, Operand(r0), SetCC); 823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, loop_statement.continue_target()); 824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register r3. 827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(result_register(), r3); 829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitAssignment(stmt->each()); 831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label stack_limit_hit, stack_check_done; 834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ StackLimitCheck(&stack_limit_hit); 837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_check_done); 838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the going to the next element by incrementing 840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the index (smi) stored on top of the stack. 841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.continue_target()); 842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); 843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r0, r0, Operand(Smi::FromInt(1))); 844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&loop); 846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Slow case for the stack limit check. 848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StackCheckStub stack_check_stub; 849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_limit_hit); 850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stack_check_stub); 851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&stack_check_done); 852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.break_target()); 855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(5); 856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 8613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 8648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang bool pretenure) { 865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // space for nested functions that don't need literals cloning. 8678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (scope()->is_function_scope() && 8688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang info->num_literals() == 0 && 8698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang !pretenure) { 870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastNewClosureStub stub; 871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(info)); 872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(info)); 8768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex 8778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang : Heap::kFalseValueRootIndex); 8788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(cp, r0, r1); 8798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CallRuntime(Runtime::kNewClosure, 3); 880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 8810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 885d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 8870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->var()); 888e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 89159151504615d929945dc59db37bf1166937748c6Steve BlockMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( 89259151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 89359151504615d929945dc59db37bf1166937748c6Steve Block Label* slow) { 89459151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(slot->type() == Slot::CONTEXT); 89559151504615d929945dc59db37bf1166937748c6Steve Block Register current = cp; 89659151504615d929945dc59db37bf1166937748c6Steve Block Register next = r3; 89759151504615d929945dc59db37bf1166937748c6Steve Block Register temp = r4; 89859151504615d929945dc59db37bf1166937748c6Steve Block 89959151504615d929945dc59db37bf1166937748c6Steve Block for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { 90059151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 90159151504615d929945dc59db37bf1166937748c6Steve Block if (s->calls_eval()) { 90259151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 90359151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); 90459151504615d929945dc59db37bf1166937748c6Steve Block __ tst(temp, temp); 90559151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, slow); 90659151504615d929945dc59db37bf1166937748c6Steve Block } 90759151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX)); 90859151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); 90959151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering cp. 91059151504615d929945dc59db37bf1166937748c6Steve Block current = next; 91159151504615d929945dc59db37bf1166937748c6Steve Block } 91259151504615d929945dc59db37bf1166937748c6Steve Block } 91359151504615d929945dc59db37bf1166937748c6Steve Block // Check that last extension is NULL. 91459151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); 91559151504615d929945dc59db37bf1166937748c6Steve Block __ tst(temp, temp); 91659151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, slow); 91759151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(temp, ContextOperand(current, Context::FCONTEXT_INDEX)); 91859151504615d929945dc59db37bf1166937748c6Steve Block return ContextOperand(temp, slot->index()); 91959151504615d929945dc59db37bf1166937748c6Steve Block} 92059151504615d929945dc59db37bf1166937748c6Steve Block 92159151504615d929945dc59db37bf1166937748c6Steve Block 92259151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( 92359151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 92459151504615d929945dc59db37bf1166937748c6Steve Block TypeofState typeof_state, 92559151504615d929945dc59db37bf1166937748c6Steve Block Label* slow, 92659151504615d929945dc59db37bf1166937748c6Steve Block Label* done) { 92759151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast-case code for variables that might be shadowed by 92859151504615d929945dc59db37bf1166937748c6Steve Block // eval-introduced variables. Eval is used a lot without 92959151504615d929945dc59db37bf1166937748c6Steve Block // introducing variables. In those cases, we do not want to 93059151504615d929945dc59db37bf1166937748c6Steve Block // perform a runtime call for all variables in the scope 93159151504615d929945dc59db37bf1166937748c6Steve Block // containing the eval. 93259151504615d929945dc59db37bf1166937748c6Steve Block if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 93359151504615d929945dc59db37bf1166937748c6Steve Block EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); 93459151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 93559151504615d929945dc59db37bf1166937748c6Steve Block } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { 9360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); 93759151504615d929945dc59db37bf1166937748c6Steve Block Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); 93859151504615d929945dc59db37bf1166937748c6Steve Block if (potential_slot != NULL) { 93959151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast case for locals that rewrite to slots. 94059151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r0, ContextSlotOperandCheckExtensions(potential_slot, slow)); 94159151504615d929945dc59db37bf1166937748c6Steve Block if (potential_slot->var()->mode() == Variable::CONST) { 94259151504615d929945dc59db37bf1166937748c6Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 94359151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(r0, ip); 94459151504615d929945dc59db37bf1166937748c6Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 94559151504615d929945dc59db37bf1166937748c6Steve Block } 94659151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 94759151504615d929945dc59db37bf1166937748c6Steve Block } else if (rewrite != NULL) { 94859151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast case for calls of an argument function. 94959151504615d929945dc59db37bf1166937748c6Steve Block Property* property = rewrite->AsProperty(); 95059151504615d929945dc59db37bf1166937748c6Steve Block if (property != NULL) { 95159151504615d929945dc59db37bf1166937748c6Steve Block VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 95259151504615d929945dc59db37bf1166937748c6Steve Block Literal* key_literal = property->key()->AsLiteral(); 95359151504615d929945dc59db37bf1166937748c6Steve Block if (obj_proxy != NULL && 95459151504615d929945dc59db37bf1166937748c6Steve Block key_literal != NULL && 95559151504615d929945dc59db37bf1166937748c6Steve Block obj_proxy->IsArguments() && 95659151504615d929945dc59db37bf1166937748c6Steve Block key_literal->handle()->IsSmi()) { 95759151504615d929945dc59db37bf1166937748c6Steve Block // Load arguments object if there are no eval-introduced 95859151504615d929945dc59db37bf1166937748c6Steve Block // variables. Then load the argument from the arguments 95959151504615d929945dc59db37bf1166937748c6Steve Block // object using keyed load. 96059151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, 9610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), 96259151504615d929945dc59db37bf1166937748c6Steve Block slow)); 96359151504615d929945dc59db37bf1166937748c6Steve Block __ mov(r0, Operand(key_literal->handle())); 96459151504615d929945dc59db37bf1166937748c6Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 9650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 96659151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 96759151504615d929945dc59db37bf1166937748c6Steve Block } 96859151504615d929945dc59db37bf1166937748c6Steve Block } 96959151504615d929945dc59db37bf1166937748c6Steve Block } 97059151504615d929945dc59db37bf1166937748c6Steve Block } 97159151504615d929945dc59db37bf1166937748c6Steve Block} 97259151504615d929945dc59db37bf1166937748c6Steve Block 97359151504615d929945dc59db37bf1166937748c6Steve Block 97459151504615d929945dc59db37bf1166937748c6Steve Blockvoid FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( 97559151504615d929945dc59db37bf1166937748c6Steve Block Slot* slot, 97659151504615d929945dc59db37bf1166937748c6Steve Block TypeofState typeof_state, 97759151504615d929945dc59db37bf1166937748c6Steve Block Label* slow) { 97859151504615d929945dc59db37bf1166937748c6Steve Block Register current = cp; 97959151504615d929945dc59db37bf1166937748c6Steve Block Register next = r1; 98059151504615d929945dc59db37bf1166937748c6Steve Block Register temp = r2; 98159151504615d929945dc59db37bf1166937748c6Steve Block 98259151504615d929945dc59db37bf1166937748c6Steve Block Scope* s = scope(); 98359151504615d929945dc59db37bf1166937748c6Steve Block while (s != NULL) { 98459151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 98559151504615d929945dc59db37bf1166937748c6Steve Block if (s->calls_eval()) { 98659151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 98759151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); 98859151504615d929945dc59db37bf1166937748c6Steve Block __ tst(temp, temp); 98959151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, slow); 99059151504615d929945dc59db37bf1166937748c6Steve Block } 99159151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 99259151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX)); 99359151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); 99459151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering cp. 99559151504615d929945dc59db37bf1166937748c6Steve Block current = next; 99659151504615d929945dc59db37bf1166937748c6Steve Block } 99759151504615d929945dc59db37bf1166937748c6Steve Block // If no outer scope calls eval, we do not need to check more 99859151504615d929945dc59db37bf1166937748c6Steve Block // context extensions. 99959151504615d929945dc59db37bf1166937748c6Steve Block if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; 100059151504615d929945dc59db37bf1166937748c6Steve Block s = s->outer_scope(); 100159151504615d929945dc59db37bf1166937748c6Steve Block } 100259151504615d929945dc59db37bf1166937748c6Steve Block 100359151504615d929945dc59db37bf1166937748c6Steve Block if (s->is_eval_scope()) { 100459151504615d929945dc59db37bf1166937748c6Steve Block Label loop, fast; 100559151504615d929945dc59db37bf1166937748c6Steve Block if (!current.is(next)) { 100659151504615d929945dc59db37bf1166937748c6Steve Block __ Move(next, current); 100759151504615d929945dc59db37bf1166937748c6Steve Block } 100859151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&loop); 100959151504615d929945dc59db37bf1166937748c6Steve Block // Terminate at global context. 101059151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); 101159151504615d929945dc59db37bf1166937748c6Steve Block __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex); 101259151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(temp, ip); 101359151504615d929945dc59db37bf1166937748c6Steve Block __ b(eq, &fast); 101459151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 101559151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); 101659151504615d929945dc59db37bf1166937748c6Steve Block __ tst(temp, temp); 101759151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, slow); 101859151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 101959151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(next, ContextOperand(next, Context::CLOSURE_INDEX)); 102059151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); 102159151504615d929945dc59db37bf1166937748c6Steve Block __ b(&loop); 102259151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&fast); 102359151504615d929945dc59db37bf1166937748c6Steve Block } 102459151504615d929945dc59db37bf1166937748c6Steve Block 10258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, GlobalObjectOperand()); 102659151504615d929945dc59db37bf1166937748c6Steve Block __ mov(r2, Operand(slot->var()->name())); 102759151504615d929945dc59db37bf1166937748c6Steve Block RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 102859151504615d929945dc59db37bf1166937748c6Steve Block ? RelocInfo::CODE_TARGET 102959151504615d929945dc59db37bf1166937748c6Steve Block : RelocInfo::CODE_TARGET_CONTEXT; 103059151504615d929945dc59db37bf1166937748c6Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 10310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 103259151504615d929945dc59db37bf1166937748c6Steve Block} 103359151504615d929945dc59db37bf1166937748c6Steve Block 103459151504615d929945dc59db37bf1166937748c6Steve Block 10350d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitVariableLoad(Variable* var) { 1036d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Four cases: non-this global variables, lookup slots, all other 1037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // types of slots, and parameters that rewrite to explicit property 1038d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // accesses on the arguments object. 10390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = var->AsSlot(); 1040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Property* property = var->AsProperty(); 1041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (var->is_global() && !var->is_this()) { 10433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "Global variable"); 10443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use inline caching. Variable name is passed in r2 and the global 1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object (receiver) in r0. 10468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, GlobalObjectOperand()); 1047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(var->name())); 10483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 10490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 10500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1051d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 105359151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 105459151504615d929945dc59db37bf1166937748c6Steve Block 105559151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 105659151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 105759151504615d929945dc59db37bf1166937748c6Steve Block EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 105859151504615d929945dc59db37bf1166937748c6Steve Block 105959151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 1060d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Lookup slot"); 1061d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ mov(r1, Operand(var->name())); 1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r1); // Context and name. 1063d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 106459151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 106559151504615d929945dc59db37bf1166937748c6Steve Block 10660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1067d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1068d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL) { 1069d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1070d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ? "Context slot" 1071d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : "Stack slot"); 1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (var->mode() == Variable::CONST) { 10730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Constants may be the hole value if they have not been initialized. 10740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Unhole them. 10750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen MemOperand slot_operand = EmitSlotSearch(slot, r0); 10760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ldr(r0, slot_operand); 10770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 10780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmp(r0, ip); 10790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 10800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 10810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 10820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(slot); 10830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1085d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Rewritten parameter"); 1086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(property); 1087d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Rewritten parameter accesses are of the form "slot[literal]". 1088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1089e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the object is in a slot. 1090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_var); 10920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* object_slot = object_var->AsSlot(); 1093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_slot); 1094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1095d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the object. 10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Move(r1, object_slot); 1097d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the key is a smi. 1099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key_literal = property->key()->AsLiteral(); 1100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(key_literal); 1101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(key_literal->handle()->IsSmi()); 1102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the key. 11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r0, Operand(key_literal->handle())); 1105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 110625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Call keyed load IC. It has arguments key and receiver in r0 and r1. 1107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 11080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 11090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 1116bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label materialized; 11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r4 = JS function, literals array 11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r3 = literal index 11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r2 = RegExp pattern 11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r1 = RegExp flags 1122bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // r0 = temp + materialized value (RegExp literal) 112380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 112480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); 11253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 112680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r0, FieldMemOperand(r4, literal_offset)); 11283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 11293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(r0, ip); 1130bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(ne, &materialized); 113180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 113280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Create regexp literal using runtime function. 113380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Result will be in r0. 11343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); 11353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(expr->pattern())); 11363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r1, Operand(expr->flags())); 11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r4, r3, r2, r1); 11383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 113980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1140bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&materialized); 1141bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1142bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(r0); 1143bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(r0, Operand(Smi::FromInt(size))); 1144bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(r0); 1145bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 114680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1147bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // After this, registers are used as follows: 1148bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // r0: Newly allocated regexp. 114980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // r1: Materialized regexp. 1150bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // r2: temp. 1151bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(r1); 1152bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CopyFields(r0, r1, r2.bit(), size / kPointerSize); 11530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, Operand(expr->constant_properties())); 11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r0, Operand(Smi::FromInt(expr->fast_elements() ? 1 : 0))); 11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r3, r2, r1, r0); 1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->depth() > 1) { 11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 11673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 11686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4); 1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in r0. 1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 11753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Mark all computed expressions that are bound to a key that 11763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // is shadowed by a later occurrence of the same key. For the 11773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // marked expressions, no store code is emitted. 11783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu expr->CalculateEmitStore(); 11793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Save result on stack 1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::CONSTANT: 1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); 1195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 11980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(value); 1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(key->handle())); 1200402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp)); 12013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 12023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 12033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu EmitCallIC(ic, RelocInfo::CODE_TARGET); 12043e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through. 1208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 1209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Duplicate receiver on stack. 1210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(sp)); 1211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 12120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 12130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 12143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 12153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ CallRuntime(Runtime::kSetProperty, 3); 12163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 12173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ Drop(3); 12183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::GETTER: 1221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::SETTER: 1222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Duplicate receiver on stack. 1223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(sp)); 1224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 12250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 1226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? 1227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(1) : 1228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(0))); 1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r1); 12300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 1231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDefineAccessor, 4); 1232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 12370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 12390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1244d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 12453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 1249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 12513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 12523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 1253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, Operand(expr->constant_elements())); 12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r3, r2, r1); 1255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) { 1256756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub stub( 1257756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); 1258756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 1259756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2); 1260756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (expr->depth() > 1) { 1261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1262756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 1263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1265756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub stub( 1266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub::CLONE_ELEMENTS, length); 1267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 12683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 12713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 12733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 12753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 12763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 12773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 12783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 12793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 12803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 12843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 12853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Store the subexpression value in the array's elements. 12903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r1, MemOperand(sp)); // Copy of array literal. 12913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); 12923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), FieldMemOperand(r1, offset)); 12943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Update the write barrier for the array store with r0 as the scratch 12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // register. 12979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r1, Operand(offset), r2, result_register()); 12983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 13010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 13030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1317402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 1318402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1319402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1320402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 132180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 132280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (property != NULL) { 132380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen assign_type = (property->key()->IsPropertyName()) 132480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? NAMED_PROPERTY 132580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : KEYED_PROPERTY; 1326402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1332402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 13360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(property->obj()); 1337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 13390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 134325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (expr->is_compound()) { 13440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 13450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(property->key()); 134625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); 134725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 134825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 13490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 13500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->key()); 135125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 1352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 13560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 13570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 13580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 13590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->target()->AsVariableProxy()->var()); 13600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 13610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 13620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 13630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 13640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 13650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 13660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 13670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 137080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 137180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ConstantOperand constant = ShouldInlineSmiCase(op) 137280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? GetConstantOperand(op, expr->target(), expr->value()) 137380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : kNoConstants; 137480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(constant == kRightConstant || constant == kNoConstants); 137580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (constant == kNoConstants) { 137680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ push(r0); // Left operand goes on the stack. 13770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 137880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 138080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 138180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? OVERWRITE_RIGHT 138280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : NO_OVERWRITE; 138380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position() + 1); 13840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 138580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 138680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen EmitInlineSmiBinaryOp(expr, 138780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 138880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mode, 138980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 139080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->value(), 139180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen constant); 139280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 13930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitBinaryOp(op, mode); 139480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 139580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 13960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1404402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 14060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen expr->op()); 1407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1415402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(key->handle())); 1422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call load IC. It has arguments receiver and property name r0 and r2. 1423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 14240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1428d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 143025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Call keyed load IC. It has arguments key and receiver in r0 and r1. 1431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 14320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, 143780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 143880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right, 144180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ConstantOperand constant) { 144280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(constant == kNoConstants); // Only handled case. 14430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitBinaryOp(op, mode); 144480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 144580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 144680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1447d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 144880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode) { 1449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 145080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenericBinaryOpStub stub(op, mode, r1, r0); 1451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 14520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 1465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 14780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 14790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(var, Token::ASSIGN); 1480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 14840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); // Restore value. 1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 14890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 14940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 14950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 1496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 1497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); 1498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); // Restore value. 1499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 15000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1507d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 15080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::Value op) { 1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand sides that rewrite to explicit property accesses do not reach 1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // here. 15113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 15120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(var->is_global() || var->AsSlot() != NULL); 1513d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 15143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1515d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in r0, variable name in 1518402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r2, and the global object in r1. 15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(var->name())); 15208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, GlobalObjectOperand()); 15213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 15220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 1525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment for non-const variables and for initialization 1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // of const variables. Const assignments are simply skipped. 1527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 15280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = var->AsSlot(); 1529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Slot::LOCAL: 1532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(fp, SlotOffset(slot))); 1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, ip); 1537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 1538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment. 1540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), MemOperand(fp, SlotOffset(slot))); 1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, r1); 1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, target); 1548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r2, ip); 1550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 1551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment and issue the write barrier. 1553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), target); 1554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // RecordWrite may destroy all its register arguments. 1555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r3, result_register()); 1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 15579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r1, Operand(offset), r2, r3); 1558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 15593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call the runtime for the assignment. The runtime will ignore 1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // const reinitialization. 1564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Value. 1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(slot->var()->name())); 1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r0); // Context and name. 1567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime will ignore const redeclaration. 1569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 15743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 15763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 15780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result_register()); 15793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 15803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value. 1594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 1602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load receiver to r1. Leave a copy in the stack if needed for turning the 1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // receiver into fast case. 1604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->ends_initialization_block()) { 1605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp)); 1606402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(r1); 1608402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1609402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 16110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Result of assignment, saved even if not needed. 1616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Receiver is under the result value. 1617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); 1618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 16210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 1622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 16230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); 1638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 1646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load receiver to r2. Leave a copy in the stack if needed for turning the 1647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // receiver into fast case. 1648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->ends_initialization_block()) { 1649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp)); 1650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); 1652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 16550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 1656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Result of assignment, saved even if not needed. 1660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Receiver is under the result value. 1661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); 1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 16650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 1666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 16670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 16770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->obj()); 1678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 1679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 16800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->obj()); 16810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->key()); 168225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ pop(r1); 1683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 16850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1688d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 1689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Object> name, 1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 16943e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 16953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 16963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 16973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 16983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ mov(r2, Operand(name)); 16993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 17013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(expr->position(), FORCED_POSITION); 17023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 17048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); 17050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 17080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 17129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 17139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Expression* key, 17149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen RelocInfo::Mode mode) { 17158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the key. 17168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(key); 17178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Swap the name of the function and the receiver on the stack to follow 17198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // the calling convention for call ICs. 17208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(r1); 17218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(r0); 17228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(r1); 17238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Code common for calls using the IC. 17259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ZoneList<Expression*>* args = expr->arguments(); 17269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int arg_count = args->length(); 17273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 17283e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 17293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 17303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 17319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 17329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source position for debugger. 17333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(expr->position(), FORCED_POSITION); 17349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call the IC initialization code. 17359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 17368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); 17378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. 17380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, mode); 17399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Restore context register. 17409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 17418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang context()->DropAndPlug(1, r0); // Drop the key still on the stack. 17429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 17439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 17449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1745d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 1746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 17493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 17503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 17513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 17523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 17553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(expr->position(), FORCED_POSITION); 1756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 17593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 17603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 17610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 1762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1765d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 1766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 1768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 1769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 1771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 1772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // resolve the function we need to call and the receiver of the 1773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. Then we call the resolved function using the given 1774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 1775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 1776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 1777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 17783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope pos_scope(masm()->positions_recorder()); 17793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(fun); 17803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 17813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(r2); // Reserved receiver slot. 1782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 17833e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push the arguments. 17843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 17853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 17863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 17873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 17883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push copy of the function - found below the arguments. 17893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); 1791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 17923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push copy of the first argument or undefined if it doesn't exist. 17933e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (arg_count > 0) { 17943e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 17953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(r1); 17963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 17973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(r2); 17983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 18003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push the receiver of the enclosing function and do runtime call. 18013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ ldr(r1, 18023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); 18033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(r1); 18043e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 18053e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 18063e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // The runtime call returns a pair of values in r0 (function) and 18073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // r1 (receiver). Touch up the stack with the right values. 18083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); 18093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ str(r1, MemOperand(sp, arg_count * kPointerSize)); 18103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 18133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(expr->position(), FORCED_POSITION); 1814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 1818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 18190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 1821402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push global object as receiver for the call IC. 18228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, GlobalObjectOperand()); 1823402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r0); 1824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 18250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (var != NULL && var->AsSlot() != NULL && 18260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot()->type() == Slot::LOOKUP) { 182759151504615d929945dc59db37bf1166937748c6Steve Block // Call to a lookup slot (dynamically introduced variable). 182859151504615d929945dc59db37bf1166937748c6Steve Block Label slow, done; 182959151504615d929945dc59db37bf1166937748c6Steve Block 18303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 18313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Generate code for loading from variables potentially shadowed 18323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // by eval-introduced variables. 18333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu EmitDynamicLoadFromSlotFastCase(var->AsSlot(), 18343e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu NOT_INSIDE_TYPEOF, 18353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu &slow, 18363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu &done); 18373e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 183859151504615d929945dc59db37bf1166937748c6Steve Block 183959151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 18400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Call the runtime to find the function to call (returned in r0) 184159151504615d929945dc59db37bf1166937748c6Steve Block // and the object holding it (returned in edx). 1842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 1843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 1844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 1845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 184659151504615d929945dc59db37bf1166937748c6Steve Block __ Push(r0, r1); // Function, receiver. 184759151504615d929945dc59db37bf1166937748c6Steve Block 184859151504615d929945dc59db37bf1166937748c6Steve Block // If fast case code has been generated, emit code to push the 184959151504615d929945dc59db37bf1166937748c6Steve Block // function and receiver and have the slow path jump around this 185059151504615d929945dc59db37bf1166937748c6Steve Block // code. 185159151504615d929945dc59db37bf1166937748c6Steve Block if (done.is_linked()) { 185259151504615d929945dc59db37bf1166937748c6Steve Block Label call; 185359151504615d929945dc59db37bf1166937748c6Steve Block __ b(&call); 185459151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 185559151504615d929945dc59db37bf1166937748c6Steve Block // Push function. 185659151504615d929945dc59db37bf1166937748c6Steve Block __ push(r0); 185759151504615d929945dc59db37bf1166937748c6Steve Block // Push global receiver. 18588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, GlobalObjectOperand()); 185959151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 186059151504615d929945dc59db37bf1166937748c6Steve Block __ push(r1); 186159151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&call); 186259151504615d929945dc59db37bf1166937748c6Steve Block } 186359151504615d929945dc59db37bf1166937748c6Steve Block 1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitCallWithStub(expr); 1865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 1866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 1867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 1868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 1869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 1870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 18713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 18723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(prop->obj()); 18733e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 18769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call to a keyed property. 18779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // For a synthetic property use keyed load IC followed by function call, 18789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // for a regular property use keyed CallIC. 18793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 18803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(prop->obj()); 18813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 188225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (prop->is_synthetic()) { 18833e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 18843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForAccumulatorValue(prop->key()); 18853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 18869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source code position for IC call. 18873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu SetSourcePosition(prop->position(), FORCED_POSITION); 188825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ pop(r1); // We do not need to keep the receiver. 188925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 18909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 18910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 18928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, GlobalObjectOperand()); 1893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 189459151504615d929945dc59db37bf1166937748c6Steve Block __ Push(r0, r1); // Function, receiver. 18959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen EmitCallWithStub(expr); 1896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 18979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 1898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 19003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 1902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 1903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // also use the fast code generator. 1904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 1905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 1906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 1907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 1908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 1909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 19103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 19113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { PreserveStatementPositionScope scope(masm()->positions_recorder()); 19123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(fun); 19133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 19158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, GlobalObjectOperand()); 1916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 1917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r1); 1918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 1919d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 19203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 19213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 19223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 19233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1924d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 192980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 193080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 193180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 193280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->expression()); 1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 1940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 194680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into r1 and r0. 1947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(arg_count)); 194880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 1949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 196480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 19650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 19660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 1967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_true); 1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 198380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 19850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 198880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 200280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 200580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kNullValueRootIndex); 2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_false); 2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, if_false); 2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); 201980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(le, if_true, if_false, fall_through); 2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 20263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(args->length() == 1); 20273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 20293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 20313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 20323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 203380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 20363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ BranchOnSmi(r0, if_false); 20383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); 203980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(ge, if_true, if_false, fall_through); 20403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 20423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 20433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 20443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 205380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 206180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(ne, if_true, if_false, fall_through); 2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2067756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2068756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ZoneList<Expression*>* args) { 2069756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2070756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ASSERT(args->length() == 1); 2071756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 20720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2073756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2074756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label materialize_true, materialize_false; 2075756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_true = NULL; 2076756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_false = NULL; 207780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2080756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2081756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only 2082756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // used in a few functions in runtime.js which should not normally be hit by 2083756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // this compiler. 2084756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ jmp(if_false); 20850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2086756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2087756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2088756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 209780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 20980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 20990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 210380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 211780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 21180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 21190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 212380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 213780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 21380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 21390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 214380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 215680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 21570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 21580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &check_frame_marker); 2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); 2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 217480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 21840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 21850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 219080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 21910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 21920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); 2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); 219680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ArgumentsAccessStub expects the key in edx and the formal 22060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // parameter count in r0. 22070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 22120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label exit; 2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &exit); 2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 22340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &null); 2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); // Map is now in r0. 2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, &null); 2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // As long as JS_FUNCTION_TYPE is the last instance type and it is 2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // LAST_JS_OBJECT_TYPE. 2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(JS_FUNCTION_TYPE)); 2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &function); 2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the constructor in the map is a function. 2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset)); 2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &non_function_constructor); 2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r0 now contains the constructor function. Grab the 2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); 2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset)); 2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex); 2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex); 2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kNullValueRootIndex); 2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING 2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 23030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 23040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif 2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 23100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 23219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber); 2322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 23253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Allocate a heap number. 23263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r4, Operand(r0)); 2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in r0 to 0.(32 random bits) in a double 2332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CpuFeatures::IsSupported(VFP3)) { 2335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(0, r1); 2336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction(ExternalReference::random_uint32_function(), 0); 2337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CpuFeatures::Scope scope(VFP3); 2339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x41300000 is the top half of 1.0 x 2^20 as a double. 2340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Create this constant using mov/orr to avoid PC relative load. 2341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, Operand(0x41000000)); 2342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ orr(r1, r1, Operand(0x300000)); 2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move 0x41300000xxxxxxxx (x = random bits) to VFP. 2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vmov(d7, r0, r1); 2345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move 0x4130000000000000 to VFP. 23469ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(r0, Operand(0, RelocInfo::NONE)); 2347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vmov(d8, r0, r1); 2348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Subtract and store the result in the heap number. 2349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vsub(d7, d7, d8); 2350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ sub(r0, r4, Operand(kHeapObjectTag)); 2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vstr(d7, r0, HeapNumber::kValueOffset); 2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, r4); 2353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(r4)); 2355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(1, r1); 2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction( 2357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ExternalReference::fill_heap_number_with_random_function(), 1); 2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 2367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 23680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 23690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 23700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 23720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 23800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 23810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 23820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 23830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(3)); 2384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 23850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); // Load the object. 2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &done); 2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); 2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 24030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 24100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 24110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_pow, 2); 24130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Load the object. 24210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); // Load the value. 2422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // r0 = value. r1 = object. 2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r1, &done); 2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); 2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 24369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3); 2437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 24390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 2445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 24470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 2450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 24510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(r0, r1); 24627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 24637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 24667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 24690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r1); 2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 24747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 24757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 24770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 24787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 24807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 24817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = r2; 24827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r3; 24837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 24857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 24877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 24887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 24897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 24907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 24917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch, 24927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 24937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 24967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 24977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 24987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 25017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 25027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 25037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 25047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 25077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the undefined value into the result register, which will 25087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 25097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 25107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 25137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 25147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 25160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 25177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 25187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 25217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 25227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 25240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 25257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 25277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 25287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = r2; 25297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = r3; 25307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r0; 25317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 25337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 25357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 25367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 25377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 25387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 25397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 25407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 25417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 25427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 25437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 25447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 25457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 25467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 25477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 25507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 25517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 25527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kEmptyStringRootIndex); 25537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 25567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 25577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 25587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, Operand(Smi::FromInt(0))); 25597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 25607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 25627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 25637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 25650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 25730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 25770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2580f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 25850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 25890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime. 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 25960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sin, 1); 25980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime. 2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 26050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_cos, 1); 26070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime function. 2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 26140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sqrt, 1); 26160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length() - 2; // For receiver and function. 26240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Receiver. 2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 26260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i + 1)); 2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 26280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(arg_count + 1)); // Function. 2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // InvokeFunction requires function in r1. Move it in there. 2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!result_register().is(r1)) __ mov(r1, result_register()); 2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeFunction(r1, count, CALL_FUNCTION); 2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 26350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 26410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 26420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 26430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kRegExpConstructResult, 3); 26450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 26510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 26520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 26530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kSwapElements, 3); 26550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 2663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Top::global_context()->jsfunction_result_caches()); 2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 26700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = r0; 2677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = r1; 267859151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(cache, ContextOperand(cp, Context::GLOBAL_INDEX)); 2679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset)); 268059151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 2681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, 2682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, not_found; 2686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 2687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset)); 2689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r2 now holds finger offset as a smi. 2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 2691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r3 now points to the start of fixed array elements. 2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex)); 2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Note side effect of PreIndex: r3 now points to the key of the pair. 2694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(key, r2); 2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, ¬_found); 2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r3, kPointerSize)); 2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 2701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cache, key); 2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 27060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2710bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 2711bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT_EQ(2, args->length()); 2712bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2713bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register right = r0; 2714bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register left = r1; 2715bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp = r2; 2716bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp2 = r3; 2717bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 27190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2720bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(left); 2721bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2722bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label done, fail, ok; 2723bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(left, Operand(right)); 2724bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(eq, &ok); 2725bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Fail if either is a non-HeapObject. 2726bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ and_(tmp, left, Operand(right)); 2727bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ tst(tmp, Operand(kSmiTagMask)); 2728bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(eq, &fail); 2729bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset)); 2730bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset)); 2731bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(tmp2, Operand(JS_REGEXP_TYPE)); 2732bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(ne, &fail); 2733bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 2734bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(tmp, Operand(tmp2)); 2735bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(ne, &fail); 2736bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset)); 2737bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset)); 2738bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(tmp, tmp2); 2739bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(eq, &ok); 2740bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&fail); 2741bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ LoadRoot(r0, Heap::kFalseValueRootIndex); 2742bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&done); 2743bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&ok); 2744bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ LoadRoot(r0, Heap::kTrueValueRootIndex); 2745bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&done); 2746bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2748bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 2749bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 2750bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 275180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { 27520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 275380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 275480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 275580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 275680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 275780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 27580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 27590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 276080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 276180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 276280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); 276380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 276480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_true); 276580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(if_false); 276680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 27670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 276880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 276980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 277080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 277180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 277280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(args->length() == 1); 27730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 277480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 277580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(r0, r0); 27760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 277780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 277880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 277980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 27808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 27818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 27828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang context()->Plug(r0); 27838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return; 27848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 27858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2787d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 2789f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 27963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 27973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 28008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, GlobalObjectOperand()); 2801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); 2802402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r0); 2803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 28043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 28053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 28063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 28073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 28080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 2809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the JS runtime function. 2813402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r2, Operand(expr->name())); 28148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, NOT_IN_LOOP); 28150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 2816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the C runtime function. 2820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 2821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 28220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2826d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->expression()->AsProperty(); 2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop == NULL && var == NULL) { 2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-property, non-variable reference is true. 2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression may have side effects. 2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 28360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(true); 2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var != NULL && 2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke !var->is_global() && 28390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot() != NULL && 28400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen var->AsSlot()->type() != Slot::LOOKUP) { 2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-global, non-dynamic variables is false. 2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression does not have side effects. 28430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(false); 2844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Property or variable reference. Call the delete builtin with 2846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object and property name as arguments. 2847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 28480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 28490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->key()); 2850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->is_global()) { 28518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, GlobalObjectOperand()); 2852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(var->name())); 2853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); 2854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-global variable. Call the runtime to look up the context 2856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // where the variable was introduced. 2857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 2858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 2859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 2860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLookupContext, 2); 2861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 2862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 2863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 2864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::DELETE, CALL_JS); 28660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 2872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 28740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Heap::kUndefinedValueRootIndex); 2875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2877d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 2879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 288380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 2884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Notice that the labels are swapped. 28860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 28870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_false, &if_true, &fall_through); 288880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VisitForControl(expr->expression(), if_true, if_false, fall_through); 28890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_false, if_true); // Labels swapped. 2890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 2894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 28950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { StackValueContext context(this); 28960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 28970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 28990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 29013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 2904d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 29050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 2906d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 2907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ tst(result_register(), Operand(kSmiTagMask)); 2908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ b(eq, &no_conversion); 2909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(r0); 2910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 2911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 29120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result_register()); 2913d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 2914d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2915d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 29164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 29174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 291880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 2919ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke UnaryOverwriteMode overwrite = 2920ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 29210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenericUnaryOpStub stub(Token::SUB, 29220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen overwrite, 29230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NO_UNARY_FLAGS); 29244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 29254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register r0. 29260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 29274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 29280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 29294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 29304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 29314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 29324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 29334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 293480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The generic unary operation stub expects the argument to be 293580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // in the accumulator register r0. 29360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 293780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label done; 29380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(expr->op()); 29390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 294080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label call_stub; 294180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ BranchOnNotSmi(r0, &call_stub); 294280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mvn(r0, Operand(r0)); 294380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Bit-clear inverted smi-tag. 294480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bic(r0, r0, Operand(kSmiTagMask)); 294580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(&done); 294680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&call_stub); 294780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 294880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen bool overwrite = expr->expression()->ResultOverwriteAllowed(); 29490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen UnaryOpFlags flags = inline_smi_code 29500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_UNARY_SMI_CODE_IN_STUB 29510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_UNARY_FLAGS; 295280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UnaryOverwriteMode mode = 295380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 29540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags); 29554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 29564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 29570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 29584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 29594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 29604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 29633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2967d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CountOperation"); 296980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 297080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 2972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // as the left-hand side. 2973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 2974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 2979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 2980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 2982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 2984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 2985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 2986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 2987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 2988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2990e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 2991e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 2992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 29930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 29940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 29953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 29970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 2998e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ip, Operand(Smi::FromInt(0))); 2999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ip); 3000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 3002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Put the object both on the stack and in the accumulator. 30030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 3005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 3006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 30070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(prop->obj()); 30080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->key()); 300925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); 301025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 3011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 3012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3015d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 3016d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &no_conversion); 3018d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(r0); 3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 3020d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 3021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 3023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 30240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 30250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 30260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 30270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 30280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 30290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 30300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(r0); 30310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 30320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 30330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(r0, MemOperand(sp, kPointerSize)); 30340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 30350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 30360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(r0, MemOperand(sp, 2 * kPointerSize)); 30370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 30380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3043d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 3044d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 304510e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu int count_value = expr->op() == Token::INC ? 1 : -1; 304680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(expr->op())) { 304710e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); 3048d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ b(vs, &stub_call); 3049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 3050d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 3051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &done); 3052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 3053d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 305410e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ sub(r0, r0, Operand(Smi::FromInt(count_value))); 3055d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 305610e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ mov(r1, Operand(Smi::FromInt(count_value))); 30576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); 3058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 3059d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 3060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in r0. 3062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 3063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 3064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 30650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 30660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 30670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 30680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 30690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For all contexts except EffectConstant We have the result on 3070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 30710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 30720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 30760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 3077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 3080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 3081402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(r1); 3082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 30830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 3084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 30850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 30860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3087e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3088e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 30890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3090e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 3094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 3095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); // Receiver. 3096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 30970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 3098e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 30990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 31000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 31030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 31073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 31083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 31093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 31103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 31110d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 31120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsEffect()); 31130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsTest()); 311480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VariableProxy* proxy = expr->AsVariableProxy(); 311580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 311680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Comment cmnt(masm_, "Global variable"); 31178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, GlobalObjectOperand()); 311880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(r2, Operand(proxy->name())); 311980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 312080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Use a regular load, not a contextual load, to avoid a reference 312180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // error. 31220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitCallIC(ic, RelocInfo::CODE_TARGET); 31230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 312480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (proxy != NULL && 31250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen proxy->var()->AsSlot() != NULL && 31260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 312759151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 312859151504615d929945dc59db37bf1166937748c6Steve Block 312959151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 313059151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 31310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = proxy->var()->AsSlot(); 313259151504615d929945dc59db37bf1166937748c6Steve Block EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 313359151504615d929945dc59db37bf1166937748c6Steve Block 313459151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 313580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(r0, Operand(proxy->name())); 313680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Push(cp, r0); 313780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 313859151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 313959151504615d929945dc59db37bf1166937748c6Steve Block 31400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 314180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 314280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // This expression cannot throw a reference error at the top level. 31430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Visit(expr); 3144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 31473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 314880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::TryLiteralCompare(Token::Value op, 314980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 315080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right, 315180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 315280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 315380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 315480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (op != Token::EQ && op != Token::EQ_STRICT) return false; 315580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 315680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for the pattern: typeof <expression> == <string literal>. 315780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Literal* right_literal = right->AsLiteral(); 315880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (right_literal == NULL) return false; 315980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<Object> right_literal_value = right_literal->handle(); 316080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (!right_literal_value->IsString()) return false; 316180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UnaryOperation* left_unary = left->AsUnaryOperation(); 316280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 316380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<String> check = Handle<String>::cast(right_literal_value); 316480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 31650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 31660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(left_unary->expression()); 31670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 316880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (check->Equals(Heap::number_symbol())) { 316980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(kSmiTagMask)); 3170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 317180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 317280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 317380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, ip); 317480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 317580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::string_symbol())) { 317680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(kSmiTagMask)); 317780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_false); 317880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 317980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 318080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 318180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 318280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 318380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_false); 318480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 318580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, Operand(FIRST_NONSTRING_TYPE)); 318680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(lt, if_true, if_false, fall_through); 318780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::boolean_symbol())) { 318880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(ip, Heap::kTrueValueRootIndex); 318980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, ip); 3190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(ip, Heap::kFalseValueRootIndex); 319280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, ip); 319380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 319480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::undefined_symbol())) { 3195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 319680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, ip); 3197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 319880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(kSmiTagMask)); 319980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_false); 320080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 320180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 320280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 320380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 320480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 320580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 320680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::function_symbol())) { 320780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(kSmiTagMask)); 320880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_false); 320980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareObjectType(r0, r1, r0, JS_FUNCTION_TYPE); 321080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_true); 321180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Regular expressions => 'function' (they are callable). 321280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareInstanceType(r1, r0, JS_REGEXP_TYPE); 321380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 321480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (check->Equals(Heap::object_symbol())) { 321580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(kSmiTagMask)); 321680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_false); 321780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(ip, Heap::kNullValueRootIndex); 321880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, ip); 321980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_true); 322080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Regular expressions => 'function', not 'object'. 322180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareObjectType(r0, r1, r0, JS_REGEXP_TYPE); 322280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_false); 322380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 322480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r0, FieldMemOperand(r1, Map::kBitFieldOffset)); 322580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); 322680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, Operand(1 << Map::kIsUndetectable)); 322780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_false); 322880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for JS objects => true. 322980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r0, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 323080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE)); 323180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(lt, if_false); 323280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, Operand(LAST_JS_OBJECT_TYPE)); 323380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(le, if_true, if_false, fall_through); 323480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 323580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 3236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 323780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 323880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return true; 3239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3242d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 324480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 3245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 3247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 3248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 325280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 32530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 32540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 325580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 325680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // First we try a fast inlined version of the compare when one of 325780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // the operands is a literal. 325880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->op(); 325980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left = expr->left(); 326080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* right = expr->right(); 326180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { 32620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 326380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return; 326480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 3265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 32660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 326780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 3268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 32690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 3270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_JS); 3271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTrueValueRootIndex); 3272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r0, ip); 327380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 32770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 3278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 3279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 328080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns 0 for true. 3281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ tst(r0, r0); 328280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 32870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 3288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = eq; 3289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 329080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 3291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 3292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 3293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through 329480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::EQ: 3295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = eq; 3296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 3299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = lt; 3300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 3303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reverse left and right sides to obtain ECMA-262 conversion order. 3304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = lt; 3305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, result_register()); 3306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 3307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 3309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reverse left and right sides to obtain ECMA-262 conversion order. 3310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = ge; 3311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, result_register()); 3312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 3313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 3315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = ge; 3316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 3319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 3320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 3322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 33240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 33250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 332680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 332780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ orr(r2, r0, Operand(r1)); 332880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ BranchOnNotSmi(r2, &slow_case); 332980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, r0); 333080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, NULL); 333180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 333280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 33330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareFlags flags = inline_smi_code 33340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ? NO_SMI_COMPARE_IN_STUB 33350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : NO_COMPARE_FLAGS; 33360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompareStub stub(cc, strict, flags, r1, r0); 3337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 33389ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 333980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, fall_through); 33403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 33413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 33423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 3344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 33450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 33473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 334980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 335080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Comment cmnt(masm_, "[ CompareToNull"); 335180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 335280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 335380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 335480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 33550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 33560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 335780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 335980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(r1, Heap::kNullValueRootIndex); 336080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, r1); 336180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (expr->is_strict()) { 336280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 336380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 336480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_true); 336580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 336680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, r1); 336780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_true); 336880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(kSmiTagMask)); 336980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_false); 337080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // It can be an undetectable object. 337180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 337280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 337380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 337480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 337580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 337680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 33770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 337880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 337980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 338080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3381d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 3382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 33830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 33870d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 33880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return r0; 33890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 33920d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 33930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return cp; 33940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 33950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 33960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 33970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { 33980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(mode == RelocInfo::CODE_TARGET || 33990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mode == RelocInfo::CODE_TARGET_CONTEXT); 34000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Call(ic, mode); 34010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3404d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 3406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(value, MemOperand(fp, frame_offset)); 3407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 34083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 341159151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(dst, ContextOperand(cp, context_index)); 34123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 34133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 3416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 3417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 3419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(r1)); 3420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 3421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 3422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address in link register to stack (smi encoded Code* delta) 3423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(r1, lr, Operand(masm_->CodeObject())); 3424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 3425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 3426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(r1, r1, Operand(r1)); // Convert to smi. 3427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r1); 3428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3431d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 3432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(r1)); 3433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 3434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 3435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address and return. 3436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 3437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 3438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 3439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(pc, r1, Operand(masm_->CodeObject())); 3440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __ 3444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 34453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 3446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 3448