full-codegen-arm.cc revision 3bec4d28b1f388dbc06a9c4276e1a03e86c52b04
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 1139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // registers, so we have to use two more registers to avoid 1144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // clobbering cp. 1154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r2, Operand(cp)); 1169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r2, Operand(r1), r3, 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) { 6699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(scratch1, 6709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Operand(Context::SlotOffset(dst->index())), 6719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen scratch2, 6729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen src); 673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitDeclaration(Variable* variable, 678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable::Mode mode, 679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FunctionLiteral* function) { 680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Declaration"); 681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(variable != NULL); // Must have been resolved. 682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Slot* slot = variable->slot(); 683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = variable->AsProperty(); 684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (slot != NULL) { 686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOCAL: 689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(ip, MemOperand(fp, SlotOffset(slot))); 692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), MemOperand(fp, SlotOffset(slot))); 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: 699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We bypass the general EmitSlotSearch because we know more about 700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // this specific context. 701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The variable in the decl always resides in the current context. 703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (FLAG_debug_code) { 705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if we have the correct context pointer. 706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, 707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX)); 708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r1, cp); 709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Check(eq, "Unexpected declaration in current context."); 710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ str(ip, CodeGenerator::ContextOperand(cp, slot->index())); 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // No write barrier since the_hole_value is in old space. 715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), 718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CodeGenerator::ContextOperand(cp, slot->index())); 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = Context::SlotOffset(slot->index()); 720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We know that we have written a function, which is not a smi. 7214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r1, Operand(cp)); 7229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r1, Operand(offset), r2, result_register()); 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: { 727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(variable->name())); 728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Declaration nodes are always introduced in one of two modes. 729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(mode == Variable::VAR || 730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke mode == Variable::CONST); 731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PropertyAttributes attr = 732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke (mode == Variable::VAR) ? NONE : READ_ONLY; 733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r1, Operand(Smi::FromInt(attr))); 734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push initial value, if any. 735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Note: For variables we must not push an initial value (such as 736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 'undefined') because we may have a (legal) redeclaration and we 737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // must not destroy the current value. 738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (mode == Variable::CONST) { 739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1, r0); 741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (function != NULL) { 742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1); 743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Push initial value for function declaration. 744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kStack); 745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(Smi::FromInt(0))); // No initial value! 747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r2, r1, r0); 748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kDeclareContextSlot, 4); 750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (prop != NULL) { 755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL || mode == Variable::CONST) { 756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We are declaring a function or constant that rewrites to a 757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // property. Use (keyed) IC to set the initial value. 758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (function != NULL) { 760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kStack); 761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(function, kAccumulator); 762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kAccumulator); 765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, result_register()); // Key. 766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); 767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); // Receiver. 769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Value in r0 is ignored (declarations are statements). 773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitDeclaration(Declaration* decl) { 779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 783d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The context is the first argument. 7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r1, Operand(pairs)); 7873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r1, r0); 7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kDeclareGlobals, 3); 7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(stmt->tag(), kStack); 800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(clause->label(), kAccumulator); 820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the comparison as if via '==='. The comparison stub expects 822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the smi vs. smi case to be handled before it is called. 823f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_case; 824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 0)); // Switch value. 8253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ orr(r2, r1, 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); 8343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0); 835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 8363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(r0, Operand(0)); 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. 12559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r1, Operand(offset), r2, result_register()); 12563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 1260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 12623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1266402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1267402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1275402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 1276402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1277402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1278402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 1279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Property* prop = expr->target()->AsProperty(); 1280402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (prop != NULL) { 1281402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu assign_type = 1282402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 1283402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1284402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1285402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1286402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1287402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1288402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1289402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1290402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1291402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1292402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 1293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kAccumulator); 1294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1295402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1296402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(prop->obj(), kStack); 1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1298402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1299402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 130025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // We need the key and receiver on both the stack and in r0 and r1. 130125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (expr->is_compound()) { 130225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->obj(), kStack); 130325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->key(), kAccumulator); 130425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); 130525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 130625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 130725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->obj(), kStack); 130825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->key(), kStack); 130925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 1310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1311402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1312402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1313402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Get value of LHS expression and 1314402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // store in on top of the stack. 1315402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1316402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1317402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kStack; 1318402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1319402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1320402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableLoad(expr->target()->AsVariableProxy()->var(), 1321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression::kValue); 1322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1323402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1324402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyLoad(prop); 1325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1326402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyLoad(prop); 1329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1332402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate RHS expression. 1336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Expression* rhs = expr->value(); 1337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu VisitForValue(rhs, kAccumulator); 1338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1339402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // If we have a compound assignment: Apply operator. 1340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Location saved_location = location_; 1342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = kAccumulator; 1343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitBinaryOp(expr->binary_op(), Expression::kValue); 1344402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu location_ = saved_location; 1345402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1349402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1354f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke expr->op(), 1355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu context_); 1356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1357402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1367d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(key->handle())); 1371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call load IC. It has arguments receiver and property name r0 and r2. 1372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1377d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 137925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Call keyed load IC. It has arguments key and receiver in r0 and r1. 1380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1385d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitBinaryOp(Token::Value op, 1386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0); 1389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 1390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context, r0); 1391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 1403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 1416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); 1417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1419f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 1421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kAccumulator); 1422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 1423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); // Restore value. 1424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 1425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 1431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 1432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kAccumulator); 1433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 1434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); 1435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); // Restore value. 1436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 1438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1444d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 1445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::Value op, 1446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::Context context) { 1447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand sides that rewrite to explicit property accesses do not reach 1448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // here. 14493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var != NULL); 14503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(var->is_global() || var->slot() != NULL); 1451d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 14523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (var->is_global()) { 1453d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!var->is_this()); 1454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a global variable. Use inline caching for the 1455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // assignment. Right-hand-side value is passed in r0, variable name in 1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r2, and the global object in r1. 14573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(var->name())); 1458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, CodeGenerator::GlobalObject()); 14593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 14603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 1463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment for non-const variables and for initialization 1464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // of const variables. Const assignments are simply skipped. 1465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 1466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Slot* slot = var->slot(); 1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (slot->type()) { 1468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Slot::PARAMETER: 1469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Slot::LOCAL: 1470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(fp, SlotOffset(slot))); 1473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, ip); 1475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 1476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment. 1478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), MemOperand(fp, SlotOffset(slot))); 1479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::CONTEXT: { 1482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MemOperand target = EmitSlotSearch(slot, r1); 1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Detect const reinitialization by checking for the hole value. 1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, target); 1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r2, ip); 1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 1489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment and issue the write barrier. 1491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(result_register(), target); 1492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // RecordWrite may destroy all its register arguments. 1493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r3, result_register()); 1494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 14959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r1, Operand(offset), r2, r3); 1496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 14973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Slot::LOOKUP: 1500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call the runtime for the assignment. The runtime will ignore 1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // const reinitialization. 1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Value. 1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(slot->var()->name())); 1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r0); // Context and name. 1505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (op == Token::INIT_CONST) { 1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime will ignore const redeclaration. 1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kStoreContextSlot, 3); 1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 15123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 15143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1516402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context, result_register()); 15173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 15183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1520d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 1524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 15253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value. 1532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 1540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load receiver to r1. Leave a copy in the stack if needed for turning the 1541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // receiver into fast case. 1542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->ends_initialization_block()) { 1543402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp)); 1544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1545402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(r1); 1546402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1547402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Result of assignment, saved even if not needed. 1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Receiver is under the result value. 1555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); 1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 1559402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu DropAndApply(1, context_, r0); 1560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, r0); 1562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1566d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 1570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 1572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 1573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 1574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 1575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); 1576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 1578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 1579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 1582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 1583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 1584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load receiver to r2. Leave a copy in the stack if needed for turning the 1585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // receiver into fast case. 1586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->ends_initialization_block()) { 1587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp)); 1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); 1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 1594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 1596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 1597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Result of assignment, saved even if not needed. 1598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Receiver is under the result value. 1599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); 1600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 1601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 1602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 1603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke DropAndApply(1, context_, r0); 1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 1606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1610d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 1611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 1613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 1615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(expr->obj(), kAccumulator); 1616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 1617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 1618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(expr->obj(), kStack); 162025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(expr->key(), kAccumulator); 162125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ pop(r1); 1622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 162325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Apply(context_, r0); 1624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 1628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Object> name, 1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 1630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 1631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 16323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 16333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 1634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 16353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1636402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r2, Operand(name)); 1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 16383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block SetSourcePosition(expr->position()); 16393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 1640402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); 1642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, mode); 1643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 1644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1645402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, r0); 1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1647d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 16499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 16509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Expression* key, 16519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen RelocInfo::Mode mode) { 16529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Code common for calls using the IC. 16539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ZoneList<Expression*>* args = expr->arguments(); 16549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int arg_count = args->length(); 16559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0; i < arg_count; i++) { 16569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen VisitForValue(args->at(i), kStack); 16579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 16589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen VisitForValue(key, kAccumulator); 16599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ mov(r2, r0); 16609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source position for debugger. 16619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen SetSourcePosition(expr->position()); 16629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call the IC initialization code. 16639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 16649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, 16659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen in_loop); 16669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ Call(ic, mode); 16679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Restore context register. 16689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 16699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Apply(context_, r0); 16709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 16719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 16729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1673d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithStub(Call* expr) { 1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 1681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 16853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 16863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, r0); 1688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1691d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* fun = expr->expression(); 1694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Variable* var = fun->AsVariableProxy()->AsVariable(); 1695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (var != NULL && var->is_possibly_eval()) { 1697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 1698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // resolve the function we need to call and the receiver of the 1699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. Then we call the resolved function using the given 1700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 1701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(fun, kStack); 1702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 1703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); // Reserved receiver slot. 1704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the arguments. 1706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 1707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 1708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 1709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(i), kStack); 1710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the function - found below the arguments. 1713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); 1715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push copy of the first argument or undefined if it doesn't exist. 1717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (arg_count > 0) { 1718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 1719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); 1720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 1722f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push the receiver of the enclosing function and do runtime call. 1725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); 1726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); 1727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 1728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The runtime call returns a pair of values in r0 (function) and 1730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r1 (receiver). Touch up the stack with the right values. 1731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r1, MemOperand(sp, arg_count * kPointerSize)); 1733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 1735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetSourcePosition(expr->position()); 1736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1738f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 1740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke DropAndApply(1, context_, r0); 1742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && !var->is_this() && var->is_global()) { 1743402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push global object as receiver for the call IC. 1744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 1745402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r0); 1746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (var != NULL && var->slot() != NULL && 1748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block var->slot()->type() == Slot::LOOKUP) { 1749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call to a lookup slot (dynamically introduced variable). Call the 1750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // runtime to find the function to call (returned in eax) and the object 1751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holding it (returned in edx). 1752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 1753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 1754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 1755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 1756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Function. 1757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); // Receiver. 1758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitCallWithStub(expr); 1759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (fun->AsProperty() != NULL) { 1760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to an object property. 1761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = fun->AsProperty(); 1762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = prop->key()->AsLiteral(); 1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key != NULL && key->handle()->IsSymbol()) { 1764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to a named property, use call IC. 1765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 1766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 17689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call to a keyed property. 17699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // For a synthetic property use keyed load IC followed by function call, 17709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // for a regular property use keyed CallIC. 1771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(prop->obj(), kStack); 177225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (prop->is_synthetic()) { 17739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen VisitForValue(prop->key(), kAccumulator); 17749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source code position for IC call. 17759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen SetSourcePosition(prop->position()); 177625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ pop(r1); // We do not need to keep the receiver. 177725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 17789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 17799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ Call(ic, RelocInfo::CODE_TARGET); 178025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Push result (function). 178125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 178225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Push Global receiver. 1783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, CodeGenerator::GlobalObject()); 1784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 178525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r1); 17869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen EmitCallWithStub(expr); 1787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 17889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 1789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 17913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 1792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call to some other expression. If the expression is an anonymous 1793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // function literal not called in a loop, mark it as one that should 1794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // also use the fast code generator. 1795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FunctionLiteral* lit = fun->AsFunctionLiteral(); 1796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (lit != NULL && 1797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lit->name()->Equals(Heap::empty_string()) && 1798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block loop_depth() == 0) { 1799d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lit->set_try_full_codegen(true); 1800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1801e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(fun, kStack); 1802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 1803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, CodeGenerator::GlobalObject()); 1804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 1805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r1); 1806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitCallWithStub(expr); 18083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1812d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 1817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push function on the stack. 1818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 1819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push global object (receiver). 1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 1823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 1827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 1828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 1833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load function, arg_count into r1 and r0. 1835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(arg_count)); 1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Function is in sp[arg_count + 1]. 1837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Replace function on TOS with result in r0, or pop it. 1843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DropAndApply(1, context_, r0); 1844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 1848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_true); 1858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 1865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 1875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 1883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kNullValueRootIndex); 1893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 1894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 1896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 1897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 1898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 1899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_false); 1900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 1901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 1902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, if_false); 1903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); 1904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(le, if_true); 1905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 19123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(args->length() == 1); 19133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 19143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch VisitForValue(args->at(0), kAccumulator); 19153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 19163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 19173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 19183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 19193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 19203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 19213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ BranchOnSmi(r0, if_false); 19223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); 19233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(ge, if_true); 19243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(if_false); 19253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 19263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Apply(context_, if_true, if_false); 19273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 19283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 19293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 1931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_true); 1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 1952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 1971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 1986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 1990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, if_false); 2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 2018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 2021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &check_frame_marker); 2025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); 2026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 2028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 2029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 2030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 2031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 2042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); 2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); 2051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); 2052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(if_false); 2054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 2056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ArgumentsAccessStub expects the key in edx and the formal 2063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // parameter count in eax. 2064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 2066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label exit; 2077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 2078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); 2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &exit); 2085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 2102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &null); 2103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); // Map is now in r0. 2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, &null); 2108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // As long as JS_FUNCTION_TYPE is the last instance type and it is 2110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // LAST_JS_OBJECT_TYPE. 2112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 2114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(JS_FUNCTION_TYPE)); 2115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &function); 2116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the constructor in the map is a function. 2118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset)); 2119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 2120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &non_function_constructor); 2121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r0 now contains the constructor function. Grab the 2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); 2125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset)); 2126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 2127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex); 2131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 2135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex); 2136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kNullValueRootIndex); 2141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_LOGGING_AND_PROFILING 2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif 2165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2171f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2172f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 0); 2173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 21789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber); 2179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 21823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Allocate a heap number. 21833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r4, Operand(r0)); 2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in r0 to 0.(32 random bits) in a double 2189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 2191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CpuFeatures::IsSupported(VFP3)) { 2192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(0, r1); 2193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction(ExternalReference::random_uint32_function(), 0); 2194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CpuFeatures::Scope scope(VFP3); 2196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x41300000 is the top half of 1.0 x 2^20 as a double. 2197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Create this constant using mov/orr to avoid PC relative load. 2198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, Operand(0x41000000)); 2199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ orr(r1, r1, Operand(0x300000)); 2200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move 0x41300000xxxxxxxx (x = random bits) to VFP. 2201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vmov(d7, r0, r1); 2202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move 0x4130000000000000 to VFP. 2203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(0)); 2204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vmov(d8, r0, r1); 2205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Subtract and store the result in the heap number. 2206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vsub(d7, d7, d8); 2207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ sub(r0, r4, Operand(kHeapObjectTag)); 2208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vstr(d7, r0, HeapNumber::kValueOffset); 2209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, r4); 2210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(r4)); 2212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ PrepareCallCFunction(1, r1); 2213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction( 2214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ExternalReference::fill_heap_number_with_random_function(), 1); 2215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 2224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 2236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 2237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(3), kStack); 2241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); // Load the object. 2250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &done); 2254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 2255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); 2256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 2257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 2258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 2266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_pow, 2); 2270f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); // Load the object. 2278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); // Load the value. 2279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // r0 = value. r1 = object. 2280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 2282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 2283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r1, &done); 2284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 2286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); 2287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 2290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 2291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 2292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 22939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3); 2294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 2302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 2304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 2307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kAccumulator); 2316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 23187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(r0, r1); 23197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 23207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 2321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 23237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 23267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, r1); 2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 23317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 23327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(0), kStack); 23347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(1), kAccumulator); 23357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 23377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 23387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = r2; 23397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r3; 23407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 23427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 23447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 23457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 23467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 23477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 23487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch, 23497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 23507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 23517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 23527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 23537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 23547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 23557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 23587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 23597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 23607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 23617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 23647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the undefined value into the result register, which will 23657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 23667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 23677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 23687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 23707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 23717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 23737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, result); 23747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 23757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 23787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 23797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(0), kStack); 23817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch VisitForValue(args->at(1), kAccumulator); 23827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 23847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 23857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = r2; 23867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = r3; 23877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r0; 23887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 23907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 23917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 23927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 23937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 23947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 23957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 23967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 23977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 23987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 23997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 24017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 24027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 24037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 24047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 24077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 24087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 24097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kEmptyStringRootIndex); 24107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 24137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 24147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 24157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, Operand(Smi::FromInt(0))); 24167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 24177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 24197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 24207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 24217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 24227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Apply(context_, result); 2423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2434f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 2445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime. 2452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sin, 1); 2455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 2460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime. 2461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_cos, 1); 2464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 2469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the runtime function. 2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kMath_sqrt, 1); 2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length() - 2; // For receiver and function. 2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); // Receiver. 2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < arg_count; i++) { 2483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(i + 1), kStack); 2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(arg_count + 1), kAccumulator); // Function. 2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // InvokeFunction requires function in r1. Move it in there. 2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!result_register().is(r1)) __ mov(r1, result_register()); 2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeFunction(r1, count, CALL_FUNCTION); 2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kRegExpConstructResult, 3); 2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 2508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(0), kStack); 2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kStack); 2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(2), kStack); 2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kSwapElements, 3); 2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 2517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 2521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Top::global_context()->jsfunction_result_caches()); 2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 2526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(args->at(1), kAccumulator); 2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = r0; 2534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = r1; 2535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX)); 2536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset)); 2537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, 2538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CodeGenerator::ContextOperand( 2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, 2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, not_found; 2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset)); 2548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r2 now holds finger offset as a smi. 2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r3 now points to the start of fixed array elements. 2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex)); 2552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Note side effect of PreIndex: r3 now points to the key of the pair. 2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(key, r2); 2554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, ¬_found); 2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r3, kPointerSize)); 2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 2558f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 2561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cache, key); 2562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 2563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2569d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 2572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 2573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 2574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 25783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 25793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 2582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 2583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); 2584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r0); 2585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 25863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 25873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 25883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 25893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 2590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(args->at(i), kStack); 2591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 2594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the JS runtime function. 2595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r2, Operand(expr->name())); 2596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 2597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block NOT_IN_LOOP); 2598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 2599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the C runtime function. 2603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 2604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, r0); 2606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2609d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 2612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->expression()->AsProperty(); 2614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 2615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop == NULL && var == NULL) { 2616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-property, non-variable reference is true. 2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression may have side effects. 2618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, true); 2620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var != NULL && 2621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke !var->is_global() && 2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke var->slot() != NULL && 2623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke var->slot()->type() != Slot::LOOKUP) { 2624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Result of deleting non-global, non-dynamic variables is false. 2625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The subexpression does not have side effects. 2626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, false); 2627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2628f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Property or variable reference. Call the delete builtin with 2629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // object and property name as arguments. 2630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 2631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 2632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->key(), kStack); 2633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (var->is_global()) { 2634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, CodeGenerator::GlobalObject()); 2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(var->name())); 2636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); 2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-global variable. Call the runtime to look up the context 2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // where the variable was introduced. 2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 2641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 2642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 2643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLookupContext, 2); 2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 2645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(var->name())); 2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 2647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::DELETE, CALL_JS); 2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 2655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 2657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 2658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kUninitialized: 2659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 2660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kEffect: 2662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValue: 2664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 2665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 2666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 2667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 2669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 2670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kTestValue: 2674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Value is false so it's needed. 2675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); 2676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (location_) { 2677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kAccumulator: 2678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case kStack: 2680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 2681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 2684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 2685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Expression::kValueTest: 2686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(false_label_); 2687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 2693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Notice that the labels are swapped. 2699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); 2700f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForControl(expr->expression(), if_true, if_false); 2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_false, if_true); // Labels swapped. 2704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 2708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (proxy != NULL && 2711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block !proxy->var()->is_this() && 2712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->is_global()) { 2713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "Global variable"); 2714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, CodeGenerator::GlobalObject()); 2715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(proxy->name())); 2716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 2717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Use a regular load, not a contextual load, to avoid a reference 2718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // error. 2719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Call(ic, RelocInfo::CODE_TARGET); 2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 2721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (proxy != NULL && 2722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot() != NULL && 2723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block proxy->var()->slot()->type() == Slot::LOOKUP) { 2724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(proxy->name())); 2725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cp, r0); 2726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 2728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This expression cannot throw a reference error at the top level. 2730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->expression(), kStack); 2731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 2734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 2735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 27363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2738d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 2739d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 2740d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke VisitForValue(expr->expression(), kAccumulator); 2741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 2742d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ tst(result_register(), Operand(kSmiTagMask)); 2743d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ b(eq, &no_conversion); 2744d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(r0); 2745d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 2746d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 2747d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Apply(context_, result_register()); 2748d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 2749d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 2750d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 27514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::SUB: { 27524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (SUB)"); 2753ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke bool can_overwrite = 27544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 27554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 2756ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke UnaryOverwriteMode overwrite = 2757ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 27584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::SUB, overwrite); 27594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 27604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register r0. 27614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 27624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 27634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, r0); 27644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 27654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 27664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 27674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke case Token::BIT_NOT: { 27684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); 2769ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke bool can_overwrite = 27704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke (expr->expression()->AsBinaryOperation() != NULL && 27714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); 2772ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke UnaryOverwriteMode overwrite = 2773ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 27744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); 27754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // GenericUnaryOpStub expects the argument to be in the 27764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // accumulator register r0. 27774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke VisitForValue(expr->expression(), kAccumulator); 27784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Avoid calling the stub for Smis. 27794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Label smi, done; 2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(result_register(), &smi); 27814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Non-smi: call stub leaving result in accumulator register. 27824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 27834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ b(&done); 27844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Perform operation directly on Smis. 27854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&smi); 27864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mvn(result_register(), Operand(result_register())); 27874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Bit-clear inverted smi-tag. 27884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bic(result_register(), result_register(), Operand(kSmiTagMask)); 27894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ bind(&done); 27904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Apply(context_, result_register()); 27914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 27924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 27934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 27963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2800d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CountOperation"); 2802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // as the left-hand side. 2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 2805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 2806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 2810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 2811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 2813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 2814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 2815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 2816e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 2817e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 2818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 2819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 2822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 2823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 2824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Location saved_location = location_; 2825d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke location_ = kAccumulator; 2826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 2827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kValue); 2828e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke location_ = saved_location; 28293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 2831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix() && context_ != Expression::kEffect) { 2832e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ip, Operand(Smi::FromInt(0))); 2833e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ip); 2834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2835e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Put the object both on the stack and in the accumulator. 2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kAccumulator); 2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 2839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 2840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForValue(prop->obj(), kStack); 284225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen VisitForValue(prop->key(), kAccumulator); 284325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); 284425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 2845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 2846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2849d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 2850d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 2851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &no_conversion); 2852d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(r0); 2853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 2854d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 2855e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2856e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 2857e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2858e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (context_) { 2859e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kUninitialized: 2860e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 2861e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kEffect: 2862e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do not save result. 2863e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2864e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValue: 2865e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTest: 2866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kValueTest: 2867e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Expression::kTestValue: 2868e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the result on the stack. If we have a named or keyed property 2869e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // we store the result under the receiver that is currently on top 2870e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the stack. 2871e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 2872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 2873e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r0); 2874e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: 2876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(r0, MemOperand(sp, kPointerSize)); 2877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: 2879e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(r0, MemOperand(sp, 2 * kPointerSize)); 2880e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2881e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2882e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2883e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 2888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 288910e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu int count_value = expr->op() == Token::INC ? 1 : -1; 2890d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (loop_depth() > 0) { 289110e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); 2892d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ b(vs, &stub_call); 2893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 2894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 2895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(r0, &done); 2896d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 2897d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 289810e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ sub(r0, r0, Operand(Smi::FromInt(count_value))); 2899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 290010e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ mov(r1, Operand(Smi::FromInt(count_value))); 29016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); 2902e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallStub(&stub); 2903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 2904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in r0. 2906e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 2907e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 2908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::ASSIGN, 2911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Expression::kEffect); 2912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 2913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 2914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 2915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 2916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 2919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Token::ASSIGN, 2920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke context_); 2921e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 2924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 2925402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(r1); 2926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 2928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 2930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 2931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2933402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Apply(context_, r0); 2934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 2938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); // Receiver. 2940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 2941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Call(ic, RelocInfo::CODE_TARGET); 2942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (context_ != Expression::kEffect) { 2944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ApplyTOS(context_); 2945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, r0); 2948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 29513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 29523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 29533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 29543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2955d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 2956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ BinaryOperation"); 2957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::COMMA: 2959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->left()); 2960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Visit(expr->right()); 2961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::OR: 2964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::AND: 2965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block EmitLogicalOperation(expr); 2966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::ADD: 2969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SUB: 2970d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::DIV: 2971d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MOD: 2972d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::MUL: 2973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_OR: 2974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_AND: 2975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::BIT_XOR: 2976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHL: 2977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::SHR: 2978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::SAR: 2979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 2980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 2981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitBinaryOp(expr->op(), context_); 2982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2984d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 2986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 29893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::EmitNullCompare(bool strict, 2991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register obj, 2992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register null_const, 2993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true, 2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false, 2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register scratch) { 2996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(obj, null_const); 2997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (strict) { 2998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 3000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 3001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 3002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(obj, ip); 3003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnSmi(obj, if_false); 3005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // It can be an undetectable object. 3006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 3007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); 3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(scratch, Operand(1 << Map::kIsUndetectable)); 3009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_true); 3010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3015d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3016d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 3017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 3020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 3024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 3025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->left(), kStack); 3027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 3029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 3030d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_JS); 3031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTrueValueRootIndex); 3032d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r0, ip); 3033e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, if_true); 3034e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3037d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 3038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kStack); 3039d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block InstanceofStub stub; 3040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3041d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ tst(r0, r0); 3042e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, if_true); // The stub returns 0 for true. 3043e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 3048e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForValue(expr->right(), kAccumulator); 3049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Condition cc = eq; 3050d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool strict = false; 3051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 3053d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block strict = true; 3054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through 3055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::EQ: { 3056d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = eq; 3057d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If either operand is constant null we do a fast compare 3059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // against null. 3060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Literal* right_literal = expr->right()->AsLiteral(); 3061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Literal* left_literal = expr->left()->AsLiteral(); 3062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (right_literal != NULL && right_literal->handle()->IsNull()) { 3063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitNullCompare(strict, r1, r0, if_true, if_false, r2); 3064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 3065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if (left_literal != NULL && left_literal->handle()->IsNull()) { 3067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitNullCompare(strict, r0, r1, if_true, if_false, r2); 3068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Apply(context_, if_true, if_false); 3069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 3074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = lt; 3075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 3078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reverse left and right sides to obtain ECMA-262 conversion order. 3079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = lt; 3080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, result_register()); 3081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 3082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3083d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 3084e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reverse left and right sides to obtain ECMA-262 conversion order. 3085d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = ge; 3086e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, result_register()); 3087d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 3088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3089d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 3090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block cc = ge; 3091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r1); 3092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 3094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 3095d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3096d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 3097d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3098d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The comparison stub expects the smi vs. smi case to be handled 3100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // before it is called. 3101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label slow_case; 3102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ orr(r2, r0, Operand(r1)); 3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ BranchOnNotSmi(r2, &slow_case); 3104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r1, r0); 3105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(cc, if_true); 3106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 3107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&slow_case); 31093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0); 3110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 3111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r0, Operand(0)); 3112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(cc, if_true); 3113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(if_false); 31143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 31153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 31163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 3118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 3119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, if_true, if_false); 3120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 31213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 3124e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 3125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Apply(context_, r0); 3126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3129d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::result_register() { return r0; } 3130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3132d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeRegister FullCodeGenerator::context_register() { return cp; } 3133e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 3137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(value, MemOperand(fp, frame_offset)); 3138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 31393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index)); 31433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 31443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 3147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 3148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3149d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 3150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(r1)); 3151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 3152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 3153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address in link register to stack (smi encoded Code* delta) 3154e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(r1, lr, Operand(masm_->CodeObject())); 3155e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 3156e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, kSmiTag); 3157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(r1, r1, Operand(r1)); // Convert to smi. 3158e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r1); 3159e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3160e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3161e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3162d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 3163e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(r1)); 3164e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 3165e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 3166e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address and return. 3167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 3168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 3169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 3170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(pc, r1, Operand(masm_->CodeObject())); 3171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __ 3175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 31763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 3177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 3179