full-codegen-arm.cc revision 7f4d5bd8c03935e2c0cd412e561b8fc5a6a880ae
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 323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "codegen-inl.h" 33d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h" 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "debug.h" 35d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h" 363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h" 376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h" 383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right. The actual 463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the 473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function. 483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o r1: the JS function object being called (ie, ourselves) 513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o cp: our context 523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o fp: our caller's frame pointer 533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o sp: stack pointer 543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o lr: return address 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout. 583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) { 593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(info_ == NULL); 603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu info_ = info; 613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (mode == PRIMARY) { 653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int locals_count = scope()->num_stack_slots(); 663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 67f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(lr, fp, cp, r1); 684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (locals_count > 0) { 694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Load undefined value here, so the value is ready for the loop 704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // below. 714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Adjust fp to point to caller's fp. 744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ add(fp, sp, Operand(2 * kPointerSize)); 753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke { Comment cmnt(masm_, "[ Allocate locals"); 774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < locals_count; i++) { 784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(ip); 794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 81d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool function_in_register = true; 834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Possibly allocate a local context. 85f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 86f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (heap_slots > 0) { 874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate local context"); 884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Argument to NewContext is the function, which is in r1. 894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(r1); 90f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (heap_slots <= FastNewContextStub::kMaximumSlots) { 91f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastNewContextStub stub(heap_slots); 92f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 93f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 94f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kNewContext, 1); 95f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke function_in_register = false; 974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Context is returned in both r0 and cp. It replaces the context 984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // passed to us. It's saved in the stack and kept live in cp. 994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Copy any necessary parameters into the context. 1013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int num_parameters = scope()->num_parameters(); 1024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke for (int i = 0; i < num_parameters; i++) { 1033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Slot* slot = scope()->parameter(i)->slot(); 1044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (slot != NULL && slot->type() == Slot::CONTEXT) { 1054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke int parameter_offset = StandardFrameConstants::kCallerSPOffset + 1064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (num_parameters - 1 - i) * kPointerSize; 1074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Load parameter from stack. 1084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ ldr(r0, MemOperand(fp, parameter_offset)); 1094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Store it in the context. 1104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r1, Operand(Context::SlotOffset(slot->index()))); 1114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ str(r0, MemOperand(cp, r1)); 1124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Update the write barrier. This clobbers all involved 1134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // registers, so we have use a third register to avoid 1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // clobbering cp. 1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r2, Operand(cp)); 1164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(r2, r1, r0); 1174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Variable* arguments = scope()->arguments()->AsVariable(); 1224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (arguments != NULL) { 1234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Function uses arguments object. 1244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmnt(masm_, "[ Allocate arguments object"); 1254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (!function_in_register) { 1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Load this again, if it's used by the local context below. 1274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } else { 1294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r3, r1); 1304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 1314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Receiver is just before the parameters on the caller's stack. 1323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int offset = scope()->num_parameters() * kPointerSize; 1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ add(r2, fp, 1343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Operand(StandardFrameConstants::kCallerSPOffset + offset)); 1353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ mov(r1, Operand(Smi::FromInt(scope()->num_parameters()))); 1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r3, r2, r1); 1374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Arguments to ArgumentsAccessStub: 1394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // function, receiver address, parameter count. 1404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // The stub will rewrite receiever and parameter count if the previous 1414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // stack frame was an arguments adapter frame. 1424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 1434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 1444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Duplicate the value; move-to-slot operation might clobber registers. 1454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r3, r0); 1464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(arguments->slot(), r0, r1, r2); 1474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Slot* dot_arguments_slot = 1483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->arguments_shadow()->AsVariable()->slot(); 1494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Move(dot_arguments_slot, r3, r1, r2); 150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke { Comment cmnt(masm_, "[ Declarations"); 154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // For named function expressions, declare the function name as a 155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant. 156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && scope()->function() != NULL) { 157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(scope()->function(), Variable::CONST, NULL); 158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Visit all the explicit declarations unless there is an illegal 160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // redeclaration. 161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->HasIllegalRedeclaration()) { 162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke scope()->VisitIllegalRedeclaration(this); 163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitDeclarations(scope()->declarations()); 165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check the stack for overflow or break request. 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Put the lr setup instruction in the delay slot. The kInstrSize is 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // added to the implicit 8 byte offset that always applies to operations 171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // with pc and gives a return address 12 bytes down. 172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block { Comment cmnt(masm_, "[ Stack check"); 1734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ LoadRoot(r2, Heap::kStackLimitRootIndex); 1744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ add(lr, pc, Operand(Assembler::kInstrSize)); 1754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(sp, Operand(r2)); 1764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke StackCheckStub stub; 1774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(pc, 1784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()), 1794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke RelocInfo::CODE_TARGET), 1804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LeaveCC, 1814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke lo); 1823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceEnter, 0); 1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ Body"); 189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu VisitStatements(function()->body()); 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(loop_depth() == 0); 1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit a 'return undefined' in case control fell off the end of the 1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // body. 1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ b(&return_label_); 207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 2093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the return value on the stack as the parameter. 2113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Runtime::TraceExit returns its parameter in r0. 2123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 2133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 2143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make sure that the constant pool is not emitted inside of the return 2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // sequence. 2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { Assembler::BlockConstPoolScope block_const_pool(masm_); 2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Here we use masm_-> instead of the __ macro to avoid the code coverage 2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // tool from instrumenting as we rely on the code size here. 2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; 2277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position()); 2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ RecordJSReturn(); 2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->mov(sp, fp); 2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->ldm(ia_w, sp, fp.bit() | lr.bit()); 2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->add(sp, sp, Operand(sp_delta)); 2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->Jump(lr); 233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check that the size of the code used for returning matches what is 2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // expected by the debugger. If the sp_delts above cannot be encoded in the 2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // add instruction the add will generate two instructions. 2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int return_sequence_length = 2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->InstructionsGeneratedSince(&check_exit_codesize); 2417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CHECK(return_sequence_length == 2427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Assembler::kJSReturnSequenceInstructions || 2437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return_sequence_length == 2447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Assembler::kJSReturnSequenceInstructions + 1); 2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 250d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Register reg) { 251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Move value into place. 261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ mov(result_register(), reg); 264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(reg); 267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Push an extra copy of the value in case it's needed. 274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(reg); 275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We always call the runtime on ARM, so push the value as argument. 279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(reg); 280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 286d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { 287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // On ARM we have to move the value into a register to do anything 298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // with it. 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Move(result_register(), slot); 300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, result_register()); 301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 306d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { 307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Nothing to do. 313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // On ARM we have to move the value into a register to do anything 318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // with it. 319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(result_register(), Operand(lit->handle())); 320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, result_register()); 321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 326d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ApplyTOS(Expression::Context context) { 327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Duplicate the value on the stack in case it's needed. 348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(ip, MemOperand(sp)); 349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ip); 350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 359d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DropAndApply(int count, 360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context, 361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register reg) { 362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!reg.is(sp)); 364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count); 376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!reg.is(result_register())) __ mov(result_register(), reg); 377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(reg, MemOperand(sp)); 381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count > 1) __ Drop(count - 1); 387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(reg, MemOperand(sp)); 388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (count == 1) { 394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(reg, MemOperand(sp)); 395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(reg); 396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { // count > 1 397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(count - 2); 398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(reg, MemOperand(sp, kPointerSize)); 399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(reg, MemOperand(sp)); 400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DoTest(context); 402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::PrepareTest(Label* materialize_true, 407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* materialize_false, 408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label** if_true, 409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label** if_false) { 410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (context_) { 411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kUninitialized: 412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke UNREACHABLE(); 413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kEffect: 415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In an effect context, the true and the false case branch to the 416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // same label. 417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = *if_false = materialize_true; 418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValue: 420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = materialize_true; 421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = materialize_false; 422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTest: 424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = true_label_; 425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = false_label_; 426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValueTest: 428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = materialize_true; 429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = false_label_; 430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTestValue: 432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_true = true_label_; 433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *if_false = materialize_false; 434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 439d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, 440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_true, 441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* materialize_false) { 442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context) { 443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(materialize_true, materialize_false); 447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: { 451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 452e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(materialize_true); 455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(materialize_false); 458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(materialize_true); 462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTrueValueRootIndex); 463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ip); 464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(materialize_false); 466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kFalseValueRootIndex); 467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ip); 468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_true); 479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTrueValueRootIndex); 485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ip); 486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(materialize_false); 493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kFalseValueRootIndex); 499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ip); 500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Convert constant control flow (true or false) to the result expected for 509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// a given expression context. 510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::Apply(Expression::Context context, bool flag) { 511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (context) { 512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kUninitialized: 513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke UNREACHABLE(); 514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kEffect: 516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValue: { 518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Heap::RootListIndex value_root_index = 519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(result_register(), value_root_index); 523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, value_root_index); 526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ip); 527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTest: 532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(flag ? true_label_ : false_label_); 533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kTestValue: 535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is false it's needed. 538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is false it's needed. 542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!flag) { 543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kFalseValueRootIndex); 544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ip); 545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(flag ? true_label_ : false_label_); 549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Expression::kValueTest: 551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (location_) { 552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kAccumulator: 553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is true it's needed. 554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case kStack: 557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If value is true it's needed. 558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (flag) { 559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTrueValueRootIndex); 560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(ip); 561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(flag ? true_label_ : false_label_); 565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 570d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DoTest(Expression::Context context) { 571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The value to test is pushed on the stack, and duplicated on the stack 572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // if necessary (for value/test and test/value contexts). 573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, true_label_); 574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_NE(NULL, false_label_); 575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call the runtime to find the boolean value of the source and then 577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // translate it into control flow to the pair of labels. 578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kToBool, 1); 579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(ip, Heap::kTrueValueRootIndex); 580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r0, ip); 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Complete based on the context. 583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (context) { 584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTest: 590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, true_label_); 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: { 595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label discard; 596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ne, &discard); 599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(true_label_); 601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, true_label_); 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: { 613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label discard; 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, &discard); 617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(false_label_); 619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ne, false_label_); 622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&discard); 625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Drop(1); 626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(true_label_); 627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (slot->type()) { 635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOCAL: 637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return MemOperand(fp, SlotOffset(slot)); 638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::CONTEXT: { 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int context_chain_length = 6403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu scope()->ContextChainLength(slot->var()->scope()); 641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadContext(scratch, context_chain_length); 642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return CodeGenerator::ContextOperand(scratch, slot->index()); 643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::LOOKUP: 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return MemOperand(r0, 0); 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 652d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Register destination, Slot* source) { 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Use destination as scratch. 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand slot_operand = EmitSlotSearch(source, destination); 655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(destination, slot_operand); 656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 659d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::Move(Slot* dst, 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register src, 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch1, 662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register scratch2) { 663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!scratch1.is(src) && !scratch2.is(src)); 665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand location = EmitSlotSearch(dst, scratch1); 666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(src, location); 667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (dst->type() == Slot::CONTEXT) { 669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); 670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(scratch1, scratch2, src); 671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable, 676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable::Mode mode, 677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FunctionLiteral* function) { 678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(variable != NULL); // Must have been resolved. 680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Slot* slot = variable->slot(); 681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = variable->AsProperty(); 682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(ip, MemOperand(fp, SlotOffset(slot))); 690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), MemOperand(fp, SlotOffset(slot))); 693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, 705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX)); 706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r1, cp); 707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(eq, "Unexpected declaration in current context."); 708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ str(ip, CodeGenerator::ContextOperand(cp, slot->index())); 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the_hole_value is in old space. 713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), 716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CodeGenerator::ContextOperand(cp, slot->index())); 717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(offset)); 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We know that we have written a function, which is not a smi. 7204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r1, Operand(cp)); 7214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ RecordWrite(r1, r2, result_register()); 722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(variable->name())); 727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(mode == Variable::VAR || 729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke mode == Variable::CONST); 730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PropertyAttributes attr = 731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke (mode == Variable::VAR) ? NONE : READ_ONLY; 732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r1, Operand(Smi::FromInt(attr))); 733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1, r0); 740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1); 742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Push initial value for function declaration. 743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kStack); 744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(Smi::FromInt(0))); // No initial value! 746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1, r0); 747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL || mode == Variable::CONST) { 755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL) { 759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kStack); 760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kAccumulator); 764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, result_register()); // Key. 765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); 766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); // Receiver. 768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Value in r0 is ignored (declarations are statements). 772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 782d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 7833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The context is the first argument. 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r1, Operand(pairs)); 7863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r1, r0); 7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(stmt->tag(), kStack); 799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(clause->label(), kAccumulator); 819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the comparison as if via '==='. The comparison stub expects 821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the smi vs. smi case to be handled before it is called. 822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_case; 823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 0)); // Switch value. 824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, r1); 825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ orr(r2, r2, r0); 826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r2, Operand(kSmiTagMask)); 827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &slow_case); 828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, r0); 829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &next_test); 830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(clause->body_target()->entry_label()); 832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_case); 834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CompareStub stub(eq, true); 835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r0, r0); 837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &next_test); 838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(clause->body_target()->entry_label()); 840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(nested_statement.break_target()); 848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(default_clause->body_target()->entry_label()); 850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(clause->body_target()->entry_label()); 857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(nested_statement.break_target()); 861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the object to enumerate over. Both SpiderMonkey and JSC 873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ignore null and undefined in contrast to the specification; see 874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ECMA-262 section 12.6.4. 875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(stmt->enumerable(), kAccumulator); 876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &exit); 879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kNullValueRootIndex); 880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &exit); 882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &convert); 886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); 887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(hs, &done_convert); 888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); 891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // TODO(kasperl): Check cache validity in generated code. This is a 895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // fast case for the JSObject::IsSimpleEnum cache validity 896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // checks. If we cannot guarantee cache validity, call the runtime 897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // system to check cache validity or get the property names in a 898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // fixed array. 899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Duplicate the enumerable object on the stack. 902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label fixed_array; 908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, r0); 909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); 910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kMetaMapRootIndex); 911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, ip); 912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &fixed_array); 913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register r0. Get the enumeration cache from it. 915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, Map::kInstanceDescriptorsOffset)); 916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset)); 917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset)); 918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Setup the four remaining stack slots. 920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Map. 921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset)); 922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push enumeration cache, enumeration cache length (as smi) and zero. 924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r2, r1, r0); 925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register r0. Iterate through that. 928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, Operand(Smi::FromInt(0))); // Map (0) - force slow check. 930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); 931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); 932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); // Fixed array length (as smi) and initial index. 934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the current count to r0, load the length to r1. 938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); 939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); // Compare to the array length. 940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(hs, loop_statement.break_target()); 941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register r3. 943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the expected map from the stack or a zero map in the 948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register r2. 949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); 950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If not, we have to filter the key. 953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label update_each; 954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); 955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); 956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r4, Operand(r2)); 957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &update_each); 958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the entry to a string or null if it isn't a property 960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // anymore. If the property has been removed while iterating, we 961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); // Enumerable. 963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r3); // Current entry. 964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); 965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r3, Operand(r0)); 966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kNullValueRootIndex); 967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r3, ip); 968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, loop_statement.continue_target()); 969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register r3. 972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(result_register(), r3); 974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitAssignment(stmt->each()); 976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label stack_limit_hit, stack_check_done; 979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ StackLimitCheck(&stack_limit_hit); 982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_check_done); 983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the going to the next element by incrementing 985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the index (smi) stored on top of the stack. 986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.continue_target()); 987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); 988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r0, r0, Operand(Smi::FromInt(1))); 989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&loop); 991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Slow case for the stack limit check. 993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StackCheckStub stack_check_stub; 994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&stack_limit_hit); 995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stack_check_stub); 996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&stack_check_done); 997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(loop_statement.break_target()); 1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(5); 1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 1003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) { 1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // space for nested functions that don't need literals cloning. 1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (scope()->is_function_scope() && info->num_literals() == 0) { 1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastNewClosureStub stub; 1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(info)); 1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(info)); 1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r0); 1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kNewClosure, 2); 1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 10223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 10233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1025d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 10263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 1027e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->var(), context_); 1028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1031d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableLoad(Variable* var, 1032e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Four cases: non-this global variables, lookup slots, all other 1034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // types of slots, and parameters that rewrite to explicit property 1035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // accesses on the arguments object. 1036d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Slot* slot = var->slot(); 1037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Property* property = var->AsProperty(); 1038d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1039d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (var->is_global() && !var->is_this()) { 10403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "Global variable"); 10413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use inline caching. Variable name is passed in r2 and the global 1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object (receiver) in r0. 10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 1044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(var->name())); 10453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, r0); 1048d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1050d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Lookup slot"); 1051d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ mov(r1, Operand(var->name())); 1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r1); // Context and name. 1053d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 1054d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context, r0); 1055d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1056d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if (slot != NULL) { 1057d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1058d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ? "Context slot" 1059d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : "Stack slot"); 1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (var->mode() == Variable::CONST) { 1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Constants may be the hole value if they have not been initialized. 1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Unhole them. 1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke MemOperand slot_operand = EmitSlotSearch(slot, r0); 1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, slot_operand); 1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, r0); 1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context, slot); 1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1076d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmnt(masm_, "Rewritten parameter"); 1077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(property); 1078d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Rewritten parameter accesses are of the form "slot[literal]". 1079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the object is in a slot. 1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 1082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_var); 1083d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Slot* object_slot = object_var->slot(); 1084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(object_slot); 1085d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the object. 10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Move(r1, object_slot); 1088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1089e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Assert that the key is a smi. 1090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key_literal = property->key()->AsLiteral(); 1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NOT_NULL(key_literal); 1092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(key_literal->handle()->IsSmi()); 1093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load the key. 10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r0, Operand(key_literal->handle())); 1096d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 109725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Call keyed load IC. It has arguments key and receiver in r0 and r1. 1098d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 110025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Apply(context, r0); 11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1105d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r4 = JS function, literals array 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r3 = literal index 11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r2 = RegExp pattern 11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r1 = RegExp flags 11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r0 = temp + return value (RegExp literal) 11143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); 11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r0, FieldMemOperand(r4, literal_offset)); 11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(r0, ip); 11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ b(ne, &done); 11223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); 11233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(expr->pattern())); 11243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r1, Operand(expr->flags())); 11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r4, r3, r2, r1); 11263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&done); 1128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1132d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 11366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, Operand(expr->constant_properties())); 11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r0, Operand(Smi::FromInt(expr->fast_elements() ? 1 : 0))); 11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r3, r2, r1, r0); 1140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->depth() > 1) { 11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 11423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4); 1144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in r0. 1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Save result on stack 1158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::CONSTANT: 1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1163e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); 1165e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 1168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kAccumulator); 1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(key->handle())); 1170402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp)); 1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through. 1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 1177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Duplicate receiver on stack. 1178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(sp)); 1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 1180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kSetProperty, 3); 1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::GETTER: 1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::SETTER: 1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Duplicate receiver on stack. 1187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(sp)); 1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(key, kStack); 1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? 1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(1) : 1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Smi::FromInt(0))); 1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r1); 1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(value, kStack); 1195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDefineAccessor, 4); 1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 12093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 1213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 1217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, Operand(expr->constant_elements())); 12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r3, r2, r1); 12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (expr->depth() > 1) { 1220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (length > FastCloneShallowArrayStub::kMaximumLength) { 1222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FastCloneShallowArrayStub stub(length); 1225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 12263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 12293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 12313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 12333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 12363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 12433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 12443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(subexpr, kAccumulator); 12463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Store the subexpression value in the array's elements. 12483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r1, MemOperand(sp)); // Copy of array literal. 12493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); 12503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), FieldMemOperand(r1, offset)); 12523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Update the write barrier for the array store with r0 as the scratch 12543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // register. 12553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(offset)); 1256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(r1, r2, result_register()); 12573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1267402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1268402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1276402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 1277402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1278402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 1280402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Property* prop = expr->target()->AsProperty(); 1281402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (prop != NULL) { 1282402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu assign_type = 1283402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1284402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1285402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1286402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1287402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1288402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1289402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1290402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1291402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1292402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 1294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kAccumulator); 1295402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1296402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 1298402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1299402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1300402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 130125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // We need the key and receiver on both the stack and in r0 and r1. 130225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (expr->is_compound()) { 130325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->obj(), kStack); 130425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->key(), kAccumulator); 130525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); 130625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 130725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 130825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->obj(), kStack); 130925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->key(), kStack); 131025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 1311402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1312402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1313402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1314402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Get value of LHS expression and 1315402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // store in on top of the stack. 1316402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1317402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1318402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kStack; 1319402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1320402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableLoad(expr->target()->AsVariableProxy()->var(), 1322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression::kValue); 1323402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1324402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyLoad(prop); 1326402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyLoad(prop); 1330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1332402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate RHS expression. 1337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression* rhs = expr->value(); 1338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(rhs, kAccumulator); 1339402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Apply operator. 1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kAccumulator; 1344402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitBinaryOp(expr->binary_op(), Expression::kValue); 1345402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1349402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke expr->op(), 1356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu context_); 1357402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1368d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(key->handle())); 1372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call load IC. It has arguments receiver and property name r0 and r2. 1373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1378d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 138025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Call keyed load IC. It has arguments key and receiver in r0 and r1. 1381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1386d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 1387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0); 1390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 1391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, r0); 1392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 1404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 1417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); 1418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 1422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kAccumulator); 1423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 1424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); // Restore value. 1425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 1426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 1432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 1433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kAccumulator); 1434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 1435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); 1436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); // Restore value. 1437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 1446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::Value op, 1447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand sides that rewrite to explicit property accesses do not reach 1449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // here. 14503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 14513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var->is_global() || var->slot() != NULL); 1452d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 14533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1454d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in r0, variable name in 1457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r2, and the global object in r1. 14583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(var->name())); 1459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, CodeGenerator::GlobalObject()); 14603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 14613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 1464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment for non-const variables and for initialization 1465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // of const variables. Const assignments are simply skipped. 1466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Slot* slot = var->slot(); 1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Slot::LOCAL: 1471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(fp, SlotOffset(slot))); 1474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, ip); 1476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 1477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment. 1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), MemOperand(fp, SlotOffset(slot))); 1480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, r1); 1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, target); 1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r2, ip); 1489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment and issue the write barrier. 1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), target); 1493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // RecordWrite may destroy all its register arguments. 1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r3, result_register()); 1495d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 1496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(offset)); 1497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ RecordWrite(r1, r2, r3); 1498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 14993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call the runtime for the assignment. The runtime will ignore 1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // const reinitialization. 1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Value. 1505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(slot->var()->name())); 1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r0); // Context and name. 1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime will ignore const redeclaration. 1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 15143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 15163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1518402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context, result_register()); 15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 15203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1522d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 15273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value. 1534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 1542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load receiver to r1. Leave a copy in the stack if needed for turning the 1543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // receiver into fast case. 1544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->ends_initialization_block()) { 1545402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp)); 1546402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1547402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(r1); 1548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Result of assignment, saved even if not needed. 1556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Receiver is under the result value. 1557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); 1558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 1561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu DropAndApply(1, context_, r0); 1562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, r0); 1564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1568d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); 1578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 1586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load receiver to r2. Leave a copy in the stack if needed for turning the 1587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // receiver into fast case. 1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->ends_initialization_block()) { 1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp)); 1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); 1592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Result of assignment, saved even if not needed. 1600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Receiver is under the result value. 1601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); 1602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke DropAndApply(1, context_, r0); 1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 1608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1612d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 1617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(expr->obj(), kAccumulator); 1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 1619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 1620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(expr->obj(), kStack); 162225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(expr->key(), kAccumulator); 162325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ pop(r1); 1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 162525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Apply(context_, r0); 1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 1630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Object> name, 1631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 1632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 1633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 16343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 16353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 1636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 16373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r2, Operand(name)); 1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 16403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SetSourcePosition(expr->position()); 16413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 1642402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1643402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 1644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, mode); 1645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1647402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, r0); 1648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1651d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 1652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 1653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 1659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 16633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 16643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, r0); 1666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1669d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 1675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 1676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // resolve the function we need to call and the receiver of the 1677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. Then we call the resolved function using the given 1678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 1679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(fun, kStack); 1680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 1681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); // Reserved receiver slot. 1682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the arguments. 1684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 1685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 1686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 1687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(i), kStack); 1688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the function - found below the arguments. 1691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); 1693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the first argument or undefined if it doesn't exist. 1695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (arg_count > 0) { 1696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 1697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); 1698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 1700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the receiver of the enclosing function and do runtime call. 1703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); 1704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); 1705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 1706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime call returns a pair of values in r0 (function) and 1708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r1 (receiver). Touch up the stack with the right values. 1709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r1, MemOperand(sp, arg_count * kPointerSize)); 1711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 1713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetSourcePosition(expr->position()); 1714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 1718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke DropAndApply(1, context_, r0); 1720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 1721402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push global object as receiver for the call IC. 1722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 1723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r0); 1724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && var->slot() != NULL && 1726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block var->slot()->type() == Slot::LOOKUP) { 1727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call to a lookup slot (dynamically introduced variable). Call the 1728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // runtime to find the function to call (returned in eax) and the object 1729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holding it (returned in edx). 1730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 1731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 1732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 1733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 1734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Function. 1735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); // Receiver. 1736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitCallWithStub(expr); 1737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 1738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 1739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 1740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 1741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 1742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 1743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a keyed property, use keyed load IC followed by function 1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // call. 1748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 174925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->key(), kAccumulator); 1750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source code position for IC call. 1751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(prop->position()); 175225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (prop->is_synthetic()) { 175325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ pop(r1); // We do not need to keep the receiver. 175425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 175525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); // Keep receiver, to call function on. 175625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 175725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 1758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (prop->is_synthetic()) { 176125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Push result (function). 176225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 176325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Push Global receiver. 1764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, CodeGenerator::GlobalObject()); 1765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 176625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r1); 1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 176825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Pop receiver. 176925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ pop(r1); 177025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Push result (function). 177125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 177225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r1); 1773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 1775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 17763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 1778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 1779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // also use the fast code generator. 1780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 1781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 1782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 1783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 1784d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 1785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(fun, kStack); 1787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 1788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, CodeGenerator::GlobalObject()); 1789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 1790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r1); 1791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 1792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 17933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 17943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 17953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1797d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push function on the stack. 1803e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 1804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object (receiver). 1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load function, arg_count into r1 and r0. 1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(arg_count)); 1821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Function is in sp[arg_count + 1]. 1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Replace function on TOS with result in r0, or pop it. 1828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, r0); 1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 1833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_true); 1843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 1850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 1868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kNullValueRootIndex); 1878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 1879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 1881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 1882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 1883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 1884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_false); 1885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 1886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 1887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, if_false); 1888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); 1889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(le, if_true); 1890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 1897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 1908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 1909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 1910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_true); 1911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 1918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 1929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 1937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 1967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 1977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &check_frame_marker); 1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); 1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); 2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); 2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); 2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ArgumentsAccessStub expects the key in edx and the formal 2029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // parameter count in eax. 2030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label exit; 2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &exit); 2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &null); 2069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); // Map is now in r0. 2073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, &null); 2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // As long as JS_FUNCTION_TYPE is the last instance type and it is 2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // LAST_JS_OBJECT_TYPE. 2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(JS_FUNCTION_TYPE)); 2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &function); 2082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the constructor in the map is a function. 2084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset)); 2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &non_function_constructor); 2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r0 now contains the constructor function. Grab the 2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); 2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset)); 2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex); 2097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex); 2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kNullValueRootIndex); 2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING 2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif 2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ AllocateHeapNumber(r4, r1, r2, &slow_allocate_heapnumber); 2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // To allocate a heap number, and ensure that it is not a smi, we 2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call the runtime function FUnaryMinus on 0, returning the double 2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -0.0. A new, distinct heap number is returned each time. 2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kNumberUnaryMinus, 1); 2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r4, Operand(r0)); 2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in r0 to 0.(32 random bits) in a double 2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CpuFeatures::IsSupported(VFP3)) { 2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(0, r1); 2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction(ExternalReference::random_uint32_function(), 0); 2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CpuFeatures::Scope scope(VFP3); 2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x41300000 is the top half of 1.0 x 2^20 as a double. 2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Create this constant using mov/orr to avoid PC relative load. 2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, Operand(0x41000000)); 2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ orr(r1, r1, Operand(0x300000)); 2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move 0x41300000xxxxxxxx (x = random bits) to VFP. 2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vmov(d7, r0, r1); 2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move 0x4130000000000000 to VFP. 2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(0)); 2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vmov(d8, r0, r1); 2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Subtract and store the result in the heap number. 2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vsub(d7, d7, d8); 2176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ sub(r0, r4, Operand(kHeapObjectTag)); 2177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vstr(d7, r0, HeapNumber::kValueOffset); 2178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, r4); 2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(r4)); 2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(1, r1); 2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction( 2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ExternalReference::fill_heap_number_with_random_function(), 1); 2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(3), kStack); 2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); // Load the object. 2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &done); 2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); 2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_pow, 2); 2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); // Load the object. 2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); // Load the value. 2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // r0 = value. r1 = object. 2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r1, &done); 2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); 2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); 2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ RecordWrite(r1, r2, r3); 2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 22887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(r0, r1); 22897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 22907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 22927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 22937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 22967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, r1); 2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 23017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 23027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(0), kStack); 23047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(1), kAccumulator); 23057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 23077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 23087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = r2; 23097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r3; 23107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 23127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 23147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 23157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 23167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 23177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 23187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch, 23197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 23207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 23217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 23227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 23237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 23247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 23257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 23287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 23297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 23307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 23317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 23347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the undefined value into the result register, which will 23357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 23367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 23377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 23407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 23417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 23437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, result); 23447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 23457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 23487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 23497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(0), kStack); 23517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(1), kAccumulator); 23527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 23547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 23557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = r2; 23567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = r3; 23577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r0; 23587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 23607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 23627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 23637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 23647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 23657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 23667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 23677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 23687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 23697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 23707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 23717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 23727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 23737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 23747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 23777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 23787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 23797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kEmptyStringRootIndex); 23807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 23837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 23847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 23857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, Operand(Smi::FromInt(0))); 23867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 23897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 23907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 23927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, result); 2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 2403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime. 2422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sin, 1); 2425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime. 2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_cos, 1); 2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime function. 2440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sqrt, 1); 2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length() - 2; // For receiver and function. 2451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); // Receiver. 2452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 2453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(i + 1), kStack); 2454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(arg_count + 1), kAccumulator); // Function. 2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // InvokeFunction requires function in r1. Move it in there. 2458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!result_register().is(r1)) __ mov(r1, result_register()); 2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 2460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeFunction(r1, count, CALL_FUNCTION); 2461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kRegExpConstructResult, 3); 2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kSwapElements, 3); 2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 2493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Top::global_context()->jsfunction_result_caches()); 2494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 2496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); 2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = r0; 2504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = r1; 2505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX)); 2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset)); 2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, 2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CodeGenerator::ContextOperand( 2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, 2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, not_found; 2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 2516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset)); 2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r2 now holds finger offset as a smi. 2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r3 now points to the start of fixed array elements. 2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex)); 2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Note side effect of PreIndex: r3 now points to the key of the pair. 2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(key, r2); 2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, ¬_found); 2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r3, kPointerSize)); 2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cache, key); 2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 25483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 25493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 2552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 2553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); 2554402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r0); 2555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 25563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 25573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 25583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 25593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 2560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 2561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the JS runtime function. 2565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r2, Operand(expr->name())); 2566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 2567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block NOT_IN_LOOP); 2568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 2569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the C runtime function. 2573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 2574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, r0); 2576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2581f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->expression()->AsProperty(); 2584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop == NULL && var == NULL) { 2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-property, non-variable reference is true. 2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression may have side effects. 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, true); 2590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var != NULL && 2591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke !var->is_global() && 2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke var->slot() != NULL && 2593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke var->slot()->type() != Slot::LOOKUP) { 2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-global, non-dynamic variables is false. 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression does not have side effects. 2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, false); 2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Property or variable reference. Call the delete builtin with 2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object and property name as arguments. 2600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kStack); 2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->is_global()) { 2604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, CodeGenerator::GlobalObject()); 2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(var->name())); 2606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); 2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-global variable. Call the runtime to look up the context 2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // where the variable was introduced. 2610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLookupContext, 2); 2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::DELETE, CALL_JS); 2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 2625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 2627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 2628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 2629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 2630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 2632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 2634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 2635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 2636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 2637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 2639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 2640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 2644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Value is false so it's needed. 2645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 2646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 2647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 2648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 2650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 2651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 2654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 2655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 2656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 2657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 2663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Notice that the labels are swapped. 2669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); 2670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForControl(expr->expression(), if_true, if_false); 2672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_false, if_true); // Labels swapped. 2674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 2678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (proxy != NULL && 2681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block !proxy->var()->is_this() && 2682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->is_global()) { 2683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "Global variable"); 2684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 2685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(proxy->name())); 2686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 2687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Use a regular load, not a contextual load, to avoid a reference 2688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // error. 2689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 2690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 2691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (proxy != NULL && 2692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot() != NULL && 2693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot()->type() == Slot::LOOKUP) { 2694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(proxy->name())); 2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r0); 2696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 2698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This expression cannot throw a reference error at the top level. 2700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 2701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 2704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 2705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 27063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 2709d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 2710d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke VisitForValue(expr->expression(), kAccumulator); 2711d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 2712d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ tst(result_register(), Operand(kSmiTagMask)); 2713d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ b(eq, &no_conversion); 2714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(r0); 2715d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 2716d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 2717d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context_, result_register()); 2718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 2719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 27214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 27224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 27234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool overwrite = 27244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 27254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 27264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::SUB, overwrite); 27274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 27284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register r0. 27294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 27304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 27314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, r0); 27324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 27334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 27344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 27354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 27364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 27374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke bool overwrite = 27384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 27394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 27404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); 27414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 27424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register r0. 27434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 27444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Avoid calling the stub for Smis. 27454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Label smi, done; 2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(result_register(), &smi); 27474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Non-smi: call stub leaving result in accumulator register. 27484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 27494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ b(&done); 27504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Perform operation directly on Smis. 27514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&smi); 27524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mvn(result_register(), Operand(result_register())); 27534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Bit-clear inverted smi-tag. 27544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bic(result_register(), result_register(), Operand(kSmiTagMask)); 27554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 27564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, result_register()); 27574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 27584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 27594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 27623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2766d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CountOperation"); 2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // as the left-hand side. 2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 2776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 2777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 2779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 2780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 2781e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 2782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 2783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 2784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 2785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 2788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 2789e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 2790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Location saved_location = location_; 2791d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke location_ = kAccumulator; 2792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 2793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kValue); 2794e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke location_ = saved_location; 27953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 2797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix() && context_ != Expression::kEffect) { 2798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ip, Operand(Smi::FromInt(0))); 2799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ip); 2800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 2802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Put the object both on the stack and in the accumulator. 2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kAccumulator); 2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 2805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 2806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 280825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->key(), kAccumulator); 280925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); 281025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 2811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 2812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2815d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 2816d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 2817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &no_conversion); 2818d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(r0); 2819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 2820d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 2821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 2823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 2825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 2826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 2827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 2828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do not save result. 2829e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 2831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 2832e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 2833e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 2834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the result on the stack. If we have a named or keyed property 2835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // we store the result under the receiver that is currently on top 2836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the stack. 2837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 2838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 2839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r0); 2840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2841e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: 2842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(r0, MemOperand(sp, kPointerSize)); 2843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: 2845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(r0, MemOperand(sp, 2 * kPointerSize)); 2846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2852d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2853d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 2854d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 285510e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu int count_value = expr->op() == Token::INC ? 1 : -1; 2856d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (loop_depth() > 0) { 285710e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); 2858d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ b(vs, &stub_call); 2859d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 2860d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 2861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &done); 2862d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 2863d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 286410e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ sub(r0, r0, Operand(Smi::FromInt(count_value))); 2865d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 286610e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ mov(r1, Operand(Smi::FromInt(count_value))); 28676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); 2868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 2869d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 2870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in r0. 2872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 2874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 2876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::ASSIGN, 2877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kEffect); 2878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 2879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 2880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 2881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 2882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 2885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::ASSIGN, 2886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke context_); 2887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 2890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 2891402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(r1); 2892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2893e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 2894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2895e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 2896e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 2897e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2898e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, r0); 2900e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2903e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 2904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 2905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); // Receiver. 2906e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 2907e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 2908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 2910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 2911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2916d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 29173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 29183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 29193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 29203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2921d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 2922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ BinaryOperation"); 2923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::COMMA: 2925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->left()); 2926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Visit(expr->right()); 2927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::OR: 2930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::AND: 2931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitLogicalOperation(expr); 2932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::ADD: 2935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SUB: 2936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::DIV: 2937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MOD: 2938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MUL: 2939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_OR: 2940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_AND: 2941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_XOR: 2942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHL: 2943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHR: 2944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::SAR: 2945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 2946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 2947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitBinaryOp(expr->op(), context_); 2948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2949e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 2952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 29553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNullCompare(bool strict, 2957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register obj, 2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register null_const, 2959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true, 2960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false, 2961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register scratch) { 2962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(obj, null_const); 2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (strict) { 2964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 2968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(obj, ip); 2969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(obj, if_false); 2971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // It can be an undetectable object. 2972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 2973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); 2974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(scratch, Operand(1 << Map::kIsUndetectable)); 2975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_true); 2976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2981d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 2982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 2985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 2986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2991d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2992e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 2993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 2995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 2996d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_JS); 2997d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTrueValueRootIndex); 2998d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r0, ip); 2999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, if_true); 3000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 3004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 3005d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 3006d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3007d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ tst(r0, r0); 3008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, if_true); // The stub returns 0 for true. 3009e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3012d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 3014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 3015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = eq; 3016d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 3017d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3018d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 3019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 3020d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through 3021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::EQ: { 3022d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = eq; 3023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If either operand is constant null we do a fast compare 3025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // against null. 3026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Literal* right_literal = expr->right()->AsLiteral(); 3027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Literal* left_literal = expr->left()->AsLiteral(); 3028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (right_literal != NULL && right_literal->handle()->IsNull()) { 3029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitNullCompare(strict, r1, r0, if_true, if_false, r2); 3030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 3031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (left_literal != NULL && left_literal->handle()->IsNull()) { 3033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitNullCompare(strict, r0, r1, if_true, if_false, r2); 3034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 3035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3037d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3039d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 3040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = lt; 3041d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3042d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 3044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reverse left and right sides to obtain ECMA-262 conversion order. 3045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = lt; 3046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, result_register()); 3047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 3048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 3050e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reverse left and right sides to obtain ECMA-262 conversion order. 3051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = ge; 3052e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, result_register()); 3053d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 3054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 3056d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = ge; 3057d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3058d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3059d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 3060d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 3061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 3063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The comparison stub expects the smi vs. smi case to be handled 3066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // before it is called. 3067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label slow_case; 3068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ orr(r2, r0, Operand(r1)); 3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnNotSmi(r2, &slow_case); 3070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r1, r0); 3071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(cc, if_true); 3072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&slow_case); 3075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CompareStub stub(cc, strict); 3076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r0, Operand(0)); 3078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(cc, if_true); 3079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 30803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 30813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 30823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 3084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 3085e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_true, if_false); 3086e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 30873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3089d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 3090e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 3091e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 3092e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3095d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return r0; } 3096d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3098d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return cp; } 3099e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3101d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 3103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(value, MemOperand(fp, frame_offset)); 3104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 31053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3107d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index)); 31093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 31103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 3113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 3114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 3116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(r1)); 3117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 3118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 3119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address in link register to stack (smi encoded Code* delta) 3120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(r1, lr, Operand(masm_->CodeObject())); 3121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 3122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 3123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(r1, r1, Operand(r1)); // Convert to smi. 3124e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r1); 3125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3128d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 3129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(r1)); 3130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 3131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 3132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address and return. 3133e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 3134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 3135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 3136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(pc, r1, Operand(masm_->CodeObject())); 3137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __ 3141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 31423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 3145