13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 23ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Redistribution and use in source and binary forms, with or without 33ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// modification, are permitted provided that the following conditions are 43ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// met: 53ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 63ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Redistributions of source code must retain the above copyright 73ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// notice, this list of conditions and the following disclaimer. 83ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Redistributions in binary form must reproduce the above 93ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// copyright notice, this list of conditions and the following 103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// disclaimer in the documentation and/or other materials provided 113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// with the distribution. 123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// * Neither the name of Google Inc. nor the names of its 133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// contributors may be used to endorse or promote products derived 143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// from this software without specific prior written permission. 153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "v8.h" 293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h" 338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h" 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "compiler.h" 35d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "debug.h" 36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h" 373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "isolate-inl.h" 383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "parser.h" 396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h" 408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#include "stub-cache.h" 413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#include "arm/code-stubs-arm.h" 433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "arm/macro-assembler-arm.h" 449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// A patch site is a location in the code which it is possible to patch. This 521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// class has a number of methods to emit the code which is patchable and the 531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// method EmitPatchInfo to record a marker back to the patchable code. This 541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit 551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// immediate value is used) is the delta from the pc to the first instruction of 561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// the patchable code. 571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED { 581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block info_emitted_ = false; 621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ~JumpPatchSite() { 661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(patch_site_.is_bound() == info_emitted_); 671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When initially emitting this ensure that a jump is always generated to skip 701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the inlined smi code. 711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitJumpIfNotSmi(Register reg, Label* target) { 721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!patch_site_.is_bound() && !info_emitted_); 73db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(reg, Operand(reg)); 761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Don't use b(al, ...) as that might emit the constant pool right after the 771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // branch. After patching when the branch is no longer unconditional 781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // execution can continue into the constant pool. 791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, target); // Always taken before patched. 801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When initially emitting this ensure that a jump is never generated to skip 831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the inlined smi code. 841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitJumpIfSmi(Register reg, Label* target) { 851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!patch_site_.is_bound() && !info_emitted_); 86db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(reg, Operand(reg)); 891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, target); // Never taken before patched. 901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitPatchInfo() { 933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (patch_site_.is_bound()) { 943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); 953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register reg; 963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch reg.set_code(delta_to_patch_site / kOff12Mask); 973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask); 981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info_emitted_ = true; 1001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 1013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 1023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(); // Signals no inlined code. 1033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block MacroAssembler* masm_; 1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label patch_site_; 1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool info_emitted_; 1111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 1121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}; 1131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(jkummerow): Obsolete as soon as x64 is updated. Remove. 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint FullCodeGenerator::self_optimization_header_size() { 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return 24; 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 1233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right. The actual 1243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the 1253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function. 1263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 1273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// o r1: the JS function object being called (i.e., ourselves) 1293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o cp: our context 1303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o fp: our caller's frame pointer 1313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o sp: stack pointer 1323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o lr: return address 1333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 1343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 1353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout. 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() { 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompilationInfo* info = info_; 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch handler_table_ = 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell( 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget))); 1423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 1443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 145f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG 146f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (strlen(FLAG_stop_at) > 0 && 147f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 148f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ stop("stop-at"); 149f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 150f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif 151f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Strict mode functions and builtins need to replace the receiver 1533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // with undefined when called as functions (without an explicit 1543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // receiver object). r5 is zero for method calls and non-zero for 1553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // function calls. 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!info->is_classic_mode() || info->is_native()) { 157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r5, Operand(0)); 159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(eq, &ok); 1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int receiver_offset = info->scope()->num_parameters() * kPointerSize; 161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r2, MemOperand(sp, receiver_offset)); 163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ok); 164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the frame (that is done below). 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int locals_count = info->scope()->num_stack_slots(); 1723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ Push(lr, fp, cp, r1); 174756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (locals_count > 0) { 175756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load undefined value here, so the value is ready for the loop 176756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // below. 177756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 178756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 179756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Adjust fp to point to caller's fp. 180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ add(fp, sp, Operand(2 * kPointerSize)); 1813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 182756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 183756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < locals_count; i++) { 184756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(ip); 1854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bool function_in_register = true; 1894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots > 0) { 193756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate local context"); 194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Argument to NewContext is the function, which is in r1. 195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(r1); 196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots <= FastNewContextStub::kMaximumSlots) { 197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastNewContextStub stub(heap_slots); 198756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 201756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick function_in_register = false; 203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Context is returned in both r0 and cp. It replaces the context 204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // passed to us. It's saved in the stack and kept live in cp. 205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy any necessary parameters into the context. 2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < num_parameters; i++) { 209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = scope()->parameter(i); 210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int parameter_offset = StandardFrameConstants::kCallerSPOffset + 212756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick (num_parameters - 1 - i) * kPointerSize; 213756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load parameter from stack. 214756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ ldr(r0, MemOperand(fp, parameter_offset)); 215756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemOperand target = ContextOperand(cp, var->index()); 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, target); 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier. 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot( 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cp, target.offset(), r0, r3, kLRHasBeenSaved, kDontSaveFPRegs); 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Variable* arguments = scope()->arguments(); 227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (arguments != NULL) { 228756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Function uses arguments object. 229756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate arguments object"); 230756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (!function_in_register) { 231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load this again, if it's used by the local context below. 232756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r3, r1); 235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 236756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Receiver is just before the parameters on the caller's stack. 2373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 2383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int offset = num_parameters * kPointerSize; 239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ add(r2, fp, 240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Operand(StandardFrameConstants::kCallerSPOffset + offset)); 2413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r1, Operand(Smi::FromInt(num_parameters))); 242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ Push(r3, r2, r1); 243756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments to ArgumentsAccessStub: 245756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // function, receiver address, parameter count. 246756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The stub will rewrite receiever and parameter count if the previous 247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // stack frame was an arguments adapter frame. 2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ArgumentsAccessStub::Type type; 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!is_classic_mode()) { 2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch type = ArgumentsAccessStub::NEW_STRICT; 2513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (function()->has_duplicate_parameters()) { 2523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; 2533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 2543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; 2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 2563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ArgumentsAccessStub stub(type); 257756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 25844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 259589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SetVar(arguments, r0, r1, r2); 260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace) { 263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Visit the declarations and body unless there is an illegal 267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // redeclaration. 268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope()->HasIllegalRedeclaration()) { 269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment cmnt(masm_, "[ Declarations"); 270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scope()->VisitIllegalRedeclaration(this); 2713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 273589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); 274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Declarations"); 275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // For named function expressions, declare the function name as a 276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // constant. 277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope()->is_function_scope() && scope()->function() != NULL) { 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VariableProxy* proxy = scope()->function(); 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(proxy->var()->mode() == CONST || 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch proxy->var()->mode() == CONST_HARMONY); 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(proxy->var()->location() != Variable::UNALLOCATED); 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitDeclaration(proxy, proxy->var()->mode(), NULL); 283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitDeclarations(scope()->declarations()); 285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Stack check"); 288589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); 289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label ok; 290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ip, Heap::kStackLimitRootIndex); 291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(sp, Operand(ip)); 292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(hs, &ok); 293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StackCheckStub stub; 294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&ok); 296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Body"); 299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(loop_depth() == 0); 300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitStatements(function()->body()); 301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(loop_depth() == 0); 302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Always emit a 'return undefined' in case control fell off the end of 306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the body. 3073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 3083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Force emit the constant pool, so it doesn't get emitted in the middle 313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the stack check table. 314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch masm()->CheckConstPool(true, false); 315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 318db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() { 319db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch __ mov(r0, Operand(Smi::FromInt(0))); 320db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch} 321db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 322db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(profiling_counter_)); 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC); 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() { 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int reset_value = FLAG_interrupt_budget; 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) { 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Self-optimization is a one-off thing: if it fails, don't try again. 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reset_value = Smi::kMaxValue; 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->IsDebuggerActive()) { 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detect debug break requests as soon as possible. 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reset_value = 10; 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(profiling_counter_)); 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(Smi::FromInt(reset_value))); 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kMaxBackEdgeWeight = 127; 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kBackEdgeDistanceDivisor = 142; 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* back_edge_target) { 353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Comment cmnt(masm_, "[ Stack check"); 354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label ok; 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_count_based_interrupts) { 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int weight = 1; 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_weighted_back_edges) { 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(back_edge_target->is_bound()); 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch weight = Min(kMaxBackEdgeWeight, 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Max(1, distance / kBackEdgeDistanceDivisor)); 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitProfilingCounterDecrement(weight); 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(pl, &ok); 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InterruptStub stub; 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(ip, Heap::kStackLimitRootIndex); 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(sp, Operand(ip)); 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &ok); 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StackCheckStub stub; 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 376086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of this PC offset to the OSR id. This is used to find 377086aeeaae12517475c22695a200be45495516549Ben Murdoch // the AST id from the unoptimized code in order to use it as a key into 378086aeeaae12517475c22695a200be45495516549Ben Murdoch // the deoptimization input data found in the optimized code. 379086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordStackCheck(stmt->OsrEntryId()); 380086aeeaae12517475c22695a200be45495516549Ben Murdoch 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_count_based_interrupts) { 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitProfilingCounterReset(); 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&ok); 386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 387086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of the OSR id to this PC. This is used if the OSR 388086aeeaae12517475c22695a200be45495516549Ben Murdoch // entry becomes the target of a bailout. We don't expect it to be, but 389086aeeaae12517475c22695a200be45495516549Ben Murdoch // we want it to work if it is. 390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); 391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ b(&return_label_); 398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 4003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 4013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the return value on the stack as the parameter. 4023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Runtime::TraceExit returns its parameter in r0. 4033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 4043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 4053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_interrupt_at_exit || FLAG_self_optimization) { 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pretend that the exit is a backwards jump to the entry. 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int weight = 1; 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (info_->ShouldSelfOptimize()) { 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch weight = FLAG_interrupt_budget / FLAG_self_opt_count; 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (FLAG_weighted_back_edges) { 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int distance = masm_->pc_offset(); 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch weight = Min(kMaxBackEdgeWeight, 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Max(1, distance / kBackEdgeDistanceDivisor)); 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitProfilingCounterDecrement(weight); 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label ok; 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(pl, &ok); 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r2); 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InterruptStub stub; 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r0); 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitProfilingCounterReset(); 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&ok); 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 4386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make sure that the constant pool is not emitted inside of the return 4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // sequence. 4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { Assembler::BlockConstPoolScope block_const_pool(masm_); 4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Here we use masm_-> instead of the __ macro to avoid the code coverage 4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // tool from instrumenting as we rely on the code size here. 4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize; 444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ RecordJSReturn(); 4466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->mov(sp, fp); 4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->ldm(ia_w, sp, fp.bit() | lr.bit()); 4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->add(sp, sp, Operand(sp_delta)); 4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block masm_->Jump(lr); 450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 4531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the size of the code used for returning is large enough 4541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // for the debugger's requirements. 4551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(Assembler::kJSReturnSequenceInstructions <= 4561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block masm_->InstructionsGeneratedSince(&check_exit_codesize)); 4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 462589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const { 463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 473589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 474589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 475589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 480589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const { 481589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 4820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 4853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (index == Heap::kUndefinedValueRootIndex || 5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kNullValueRootIndex || 5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kFalseValueRootIndex) { 514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (index == Heap::kTrueValueRootIndex) { 516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 5193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 5300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 5310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5340d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Immediates cannot be pushed directly. 5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsTrue() || lit->IsJSObject()) { 550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 5538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 5580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count, 5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(count > 0); 5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int count, 5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count > 1) __ Drop(count - 1); 5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(reg, MemOperand(sp, 0)); 592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count, 5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(count > 0); 5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 6023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 6030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6060d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 6070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(materialize_true == materialize_false); 6090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 6100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 6150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 6220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 6280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 6290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kTrueValueRootIndex); 6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(ip); 6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kFalseValueRootIndex); 6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(ip); 6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 6380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(materialize_true == true_label_); 644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(materialize_false == false_label_); 6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const { 6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 6550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), value_root_index); 6560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 6600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 6610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 6620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, value_root_index); 6630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(ip); 6640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6670d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 6730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ b(true_label_); 6740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ b(false_label_); 676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 6803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition, 6813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* if_true, 68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 68380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 6848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ToBooleanStub stub(result_register()); 686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(result_register(), result_register()); 688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Call the runtime to find the boolean value of the source and then 690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // translate it into control flow to the pair of labels. 691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(result_register()); 692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallRuntime(Runtime::kToBool, 1); 693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ip, Heap::kFalseValueRootIndex); 694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(r0, ip); 695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(ne, if_true, if_false, fall_through); 69780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 7001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid FullCodeGenerator::Split(Condition cond, 70180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 70280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 70380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 70480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 7051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(cond, if_true); 70680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 7071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(NegateCondition(cond), if_false); 70880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 7091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(cond, if_true); 71080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(if_false); 711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 715589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) { 716589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated()); 717589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Offset is negative because higher indexes are at lower addresses. 718589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = -var->index() * kPointerSize; 719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Adjust by a (parameter or local) base offset. 720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsParameter()) { 721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += (info_->scope()->num_parameters() + 1) * kPointerSize; 722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += JavaScriptFrameConstants::kLocal0Offset; 724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 725589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return MemOperand(fp, offset); 726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 729589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 730589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 731589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_chain_length = scope()->ContextChainLength(var->scope()); 733589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ LoadContext(scratch, context_chain_length); 734589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(scratch, var->index()); 735589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 736589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return StackOperand(var); 737589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 738589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 739589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 740589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 741589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) { 742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Use destination as scratch. 743589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, dest); 744589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(dest, location); 745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 748589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var, 749589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register src, 750589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch0, 751589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1) { 752589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(!scratch0.is(src)); 754589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(!scratch0.is(scratch1)); 755589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(!scratch1.is(src)); 756589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, scratch0); 757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(src, location); 7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(scratch0, 7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch location.offset(), 7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch src, 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, 7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 767e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool should_normalize, 773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_true, 774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_false) { 775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only prepare for bailouts before splits if we're in a test 776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // context. Otherwise, we let the Visit function deal with the 777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // preparation to avoid preparing with the same AST id twice. 778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!context()->IsTest() || !info_->IsOptimizable()) return; 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label skip; 781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (should_normalize) __ b(&skip); 7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailout(expr, TOS_REG); 783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (should_normalize) { 784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ LoadRoot(ip, Heap::kTrueValueRootIndex); 785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r0, ip); 786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Split(eq, if_true, if_false, NULL); 787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&skip); 788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 792589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VariableMode mode, 7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FunctionLiteral* function) { 795589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If it was not possible to allocate the variable at compile time, we 796589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // need to "declare" it at runtime to make sure it actually exists in the 797589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // local context. 798589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* variable = proxy->var(); 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool binding_needs_init = (function == NULL) && 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (mode == CONST || mode == CONST_HARMONY || mode == LET); 801589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (variable->location()) { 802589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++global_count_; 804589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 805589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 806589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 807589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 80869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (function != NULL) { 809589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 81069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch VisitForAccumulatorValue(function); 811589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(result_register(), StackOperand(variable)); 8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (binding_needs_init) { 813589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 81469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 815589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(ip, StackOperand(variable)); 816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 81769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 819589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: 82069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // The variable in the decl always resides in the current function 82169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // context. 82269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 82369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (FLAG_debug_code) { 82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Check that we're not inside a with or catch context. 82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); 82669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(r1, Heap::kWithContextMapRootIndex); 82769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Check(ne, "Declaration in with context."); 82869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); 82969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Check(ne, "Declaration in catch context."); 8301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 83169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (function != NULL) { 832589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 83369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch VisitForAccumulatorValue(function); 834589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(result_register(), ContextOperand(cp, variable->index())); 835589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = Context::SlotOffset(variable->index()); 83669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // We know that we have written a function, which is not a smi. 8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(cp, 8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result_register(), 8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r2, 8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, 8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (binding_needs_init) { 847589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 84869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 849589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(ip, ContextOperand(cp, variable->index())); 85069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // No write barrier since the_hole_value is in old space. 851589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 85269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 85369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 855589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: { 856589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "[ Declaration"); 85769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(r2, Operand(variable->name())); 8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Declaration nodes are always introduced in one of four modes. 8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(mode == VAR || 8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode == CONST || 8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode == CONST_HARMONY || 8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode == LET); 8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) 8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? READ_ONLY : NONE; 86569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(r1, Operand(Smi::FromInt(attr))); 86669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Push initial value, if any. 86769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Note: For variables we must not push an initial value (such as 86869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // 'undefined') because we may have a (legal) redeclaration and we 86969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // must not destroy the current value. 87069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (function != NULL) { 87169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(cp, r2, r1); 87269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Push initial value for function declaration. 87369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch VisitForStackValue(function); 8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (binding_needs_init) { 87569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 87669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(cp, r2, r1, r0); 87769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 878589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r0, Operand(Smi::FromInt(0))); // Indicates no initial value. 87969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(cp, r2, r1, r0); 88069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 88169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CallRuntime(Runtime::kDeclareContextSlot, 4); 88269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The context is the first argument. 891589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r1, Operand(pairs)); 892589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); 893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r1, r0); 894589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kDeclareGlobals, 3); 8953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 8963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 9050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 9158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clause->body_target()->Unuse(); 9161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 917f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 9280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 93080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 0)); // Switch value. 9320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 9331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 9340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 93580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 93680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ orr(r2, r1, r0); 9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block patch_site.EmitJumpIfNotSmi(r2, &slow_case); 9381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 93980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, r0); 94080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(ne, &next_test); 94180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 9428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(clause->body_target()); 9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow_case); 94480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 94580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 9461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position before stub call for type feedback. 9471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetSourcePosition(clause->position()); 9481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); 9503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 9521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(r0, Operand(0)); 953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &next_test); 954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 9558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(clause->body_target()); 956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 96369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(nested_statement.break_label()); 964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 9658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(default_clause->body_target()); 966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 9728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(clause->body_target()); 97344f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); 974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 97769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(nested_statement.break_label()); 978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the object to enumerate over. Both SpiderMonkey and JSC 991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ignore null and undefined in contrast to the specification; see 992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ECMA-262 section 12.6.4. 9930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &exit); 997e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register null_value = r5; 998e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(null_value, Heap::kNullValueRootIndex); 999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(r0, null_value); 1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &exit); 1001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 10061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &convert); 10073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 10083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(ge, &done_convert); 1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 1013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for proxies. 10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_runtime; 10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); 10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(le, &call_runtime); 10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check cache validity in generated code. This is a fast case for 1022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the JSObject::IsSimpleEnum cache validity checks. If we cannot 1023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // guarantee cache validity, call the runtime system to check cache 1024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // validity or get the property names in a fixed array. 10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckEnumCache(null_value, &call_runtime); 1026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The enum cache is valid. Load the map of the object being 1028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // iterated over and use the cache for the iteration. 1029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label use_cache; 1030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 1031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&use_cache); 1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 1034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&call_runtime); 1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Duplicate the enumerable object on the stack. 1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label fixed_array; 1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, r0); 1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); 1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kMetaMapRootIndex); 1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, ip); 1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &fixed_array); 1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register r0. Get the enumeration cache from it. 1049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&use_cache); 1050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadInstanceDescriptors(r0, r1); 1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset)); 1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the four remaining stack slots. 1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Map. 1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset)); 1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push enumeration cache, enumeration cache length (as smi) and zero. 1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r2, r1, r0); 1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register r0. Iterate through that. 10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label non_proxy; 1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell( 10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object>( 10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker))); 10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordTypeFeedbackCell(stmt->PrepareId(), cell); 10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(r1, cell); 10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); 10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset)); 10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check 10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object 10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); 10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(gt, &non_proxy); 10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy 10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&non_proxy); 10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(r1, r0); // Smi and array 1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); 1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); // Fixed array length (as smi) and initial index. 1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the current count to r0, load the length to r1. 1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); 1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); // Compare to the array length. 109369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(hs, loop_statement.break_label()); 1094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register r3. 1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the expected map from the stack or a smi in the 1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register r2. 1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); 1103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If not, we may have to filter the key. 1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label update_each; 1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); 1108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); 1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r4, Operand(r2)); 1110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &update_each); 1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For proxies, no filtering is done. 11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r2, Operand(Smi::FromInt(0))); 11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &update_each); 11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Convert the entry to a string or (smi) 0 if it isn't a property 1118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // any more. If the property has been removed while iterating, we 1119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 1120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); // Enumerable. 1121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r3); // Current entry. 1122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r3, Operand(r0), SetCC); 112469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(eq, loop_statement.continue_label()); 1125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 1127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register r3. 1128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 1129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(result_register(), r3); 1130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { EffectContext context(this); 11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAssignment(stmt->each()); 1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 1136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 1137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the going to the next element by incrementing 1139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the index (smi) stored on top of the stack. 114069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.continue_label()); 1141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); 1142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r0, r0, Operand(Smi::FromInt(1))); 1143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitStackCheck(stmt, &loop); 1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(&loop); 1147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 114969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.break_label()); 1150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(5); 1151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 11573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 11608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang bool pretenure) { 1161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 1162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // space for nested functions that don't need literals cloning. If 1163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // we're running with the --always-opt or the --prepare-always-opt 1164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // flag, we need to use the runtime function so that the new function 1165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // we are creating here gets a chance to have its code optimized and 1166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // doesn't just get a copy of the existing unoptimized code. 1167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!FLAG_always_opt && 1168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !FLAG_prepare_always_opt && 116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block !pretenure && 1170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scope()->is_function_scope() && 117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block info->num_literals() == 0) { 11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastNewClosureStub stub(info->language_mode()); 1173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(info)); 1174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(info)); 11788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex 11798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang : Heap::kFalseValueRootIndex); 11808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(cp, r0, r1); 11818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CallRuntime(Runtime::kNewClosure, 3); 1182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 11830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 11843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1187d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 11893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr); 1190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, 1194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TypeofState typeof_state, 1195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 1196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register current = cp; 1197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register next = r1; 1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp = r2; 1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Scope* s = scope(); 1201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch while (s != NULL) { 1202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (s->num_heap_slots() > 0) { 12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (s->calls_non_strict_eval()) { 1204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that extension is NULL. 1205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); 1206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ tst(temp, temp); 1207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(ne, slow); 1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load next context in chain. 12103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(next, ContextOperand(current, Context::PREVIOUS_INDEX)); 1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Walk the rest of the chain without clobbering cp. 1212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current = next; 1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If no outer scope calls eval, we do not need to check more 1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // context extensions. 12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; 1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch s = s->outer_scope(); 1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (s->is_eval_scope()) { 1221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop, fast; 1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!current.is(next)) { 1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(next, current); 1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 1226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Terminate at global context. 1227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); 1228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex); 1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(temp, ip); 1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(eq, &fast); 1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that extension is NULL. 1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); 1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ tst(temp, temp); 1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(ne, slow); 1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load next context in chain. 12363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); 1237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(&loop); 1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&fast); 1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r0, GlobalObjectOperand()); 1242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r2, Operand(var->name())); 1243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 1244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? RelocInfo::CODE_TARGET 1245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : RelocInfo::CODE_TARGET_CONTEXT; 1246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, mode); 1248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1251589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1252589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 1253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot()); 1254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = cp; 125559151504615d929945dc59db37bf1166937748c6Steve Block Register next = r3; 125659151504615d929945dc59db37bf1166937748c6Steve Block Register temp = r4; 125759151504615d929945dc59db37bf1166937748c6Steve Block 1258589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 125959151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (s->calls_non_strict_eval()) { 126159151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 1262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); 126359151504615d929945dc59db37bf1166937748c6Steve Block __ tst(temp, temp); 126459151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, slow); 126559151504615d929945dc59db37bf1166937748c6Steve Block } 12663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(next, ContextOperand(context, Context::PREVIOUS_INDEX)); 126759151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering cp. 1268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context = next; 126959151504615d929945dc59db37bf1166937748c6Steve Block } 127059151504615d929945dc59db37bf1166937748c6Steve Block } 127159151504615d929945dc59db37bf1166937748c6Steve Block // Check that last extension is NULL. 1272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); 127359151504615d929945dc59db37bf1166937748c6Steve Block __ tst(temp, temp); 127459151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, slow); 1275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This function is used only for loads, not stores, so it's safe to 1277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // return an cp-based operand (the write barrier cannot be allowed to 1278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destroy the cp register). 1279589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(context, var->index()); 128059151504615d929945dc59db37bf1166937748c6Steve Block} 128159151504615d929945dc59db37bf1166937748c6Steve Block 128259151504615d929945dc59db37bf1166937748c6Steve Block 1283589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, 1284589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TypeofState typeof_state, 1285589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow, 1286589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* done) { 128759151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast-case code for variables that might be shadowed by 128859151504615d929945dc59db37bf1166937748c6Steve Block // eval-introduced variables. Eval is used a lot without 128959151504615d929945dc59db37bf1166937748c6Steve Block // introducing variables. In those cases, we do not want to 129059151504615d929945dc59db37bf1166937748c6Steve Block // perform a runtime call for all variables in the scope 129159151504615d929945dc59db37bf1166937748c6Steve Block // containing the eval. 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == DYNAMIC_GLOBAL) { 1293589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 129459151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == DYNAMIC_LOCAL) { 1296589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* local = var->local_if_not_shadowed(); 1297589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (local->mode() == CONST || 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch local->mode() == CONST_HARMONY || 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch local->mode() == LET) { 1301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (local->mode() == CONST) { 13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { // LET || CONST_HARMONY 13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, done); 13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(var->name())); 13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 131059151504615d929945dc59db37bf1166937748c6Steve Block } 1311589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(done); 131259151504615d929945dc59db37bf1166937748c6Steve Block } 131359151504615d929945dc59db37bf1166937748c6Steve Block} 131459151504615d929945dc59db37bf1166937748c6Steve Block 131559151504615d929945dc59db37bf1166937748c6Steve Block 13163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 13173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Record position before possible IC call. 13183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SetSourcePosition(proxy->position()); 13193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Variable* var = proxy->var(); 13203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1321589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Three cases: global variables, lookup variables, and all other types of 1322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // variables. 1323589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 1324589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: { 1325589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "Global variable"); 1326589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Use inline caching. Variable name is passed in r2 and the global 1327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // object (receiver) in r0. 1328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r0, GlobalObjectOperand()); 1329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r2, Operand(var->name())); 1330589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 1332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(r0); 1333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 133559151504615d929945dc59db37bf1166937748c6Steve Block 1336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 1337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 1338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 1339589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, var->IsContextSlot() 1340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ? "Context variable" 1341589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch : "Stack variable"); 13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->binding_needs_init()) { 13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // var->scope() may be NULL when the proxy is located in eval code and 13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // refers to a potential outside binding. Currently those bindings are 13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // always looked up dynamically, i.e. in that case 13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // var->location() == LOOKUP. 13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // always holds. 13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(var->scope() != NULL); 13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the binding really needs an initialization check. The check 13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // can be skipped in the following situation: we have a LET or CONST 13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding in harmony mode, both the Variable and the VariableProxy have 13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the same declaration scope (i.e. they are both in global code, in the 13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // same function or in the same eval code) and the VariableProxy is in 13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the source physically located after the initializer of the variable. 13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We cannot skip any initialization checks for CONST in non-harmony 13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // mode because const variables may be declared but never initialized: 13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // if (false) { const x; }; var y = x; 13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The condition on the declaration scopes is a conservative check for 13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // nested functions that access a binding and are called before the 13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding is initialized: 13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function() { f(); let x = 1; function f() { x = 2; } } 13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool skip_init_check; 13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { 13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch skip_init_check = false; 1369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that we always have valid source position. 13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(var->initializer_position() != RelocInfo::kNoPosition); 13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(proxy->position() != RelocInfo::kNoPosition); 13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch skip_init_check = var->mode() != CONST && 13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var->initializer_position() < proxy->position(); 13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!skip_init_check) { 13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Let and const need a read barrier. 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetVar(r0, var); 13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == LET || var->mode() == CONST_HARMONY) { 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Throw a reference error when using an uninitialized let/const 13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding in harmony mode. 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &done); 13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(var->name())); 13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 13903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Uninitalized const bindings outside of harmony mode are unholed. 13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(var->mode() == CONST); 13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(r0); 13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1397589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1398589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(var); 1400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1402d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: { 1404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label done, slow; 1405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Generate code for loading from variables potentially shadowed 1406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // by eval-introduced variables. 1407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); 1408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 1409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Comment cmnt(masm_, "Lookup variable"); 1410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r1, Operand(var->name())); 1411589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r1); // Context and name. 1412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kLoadContextSlot, 2); 141369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&done); 141469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(r0); 14150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 14163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 14183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1420d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 1422bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label materialized; 14233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 1424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // r5 = materialized value (RegExp literal) 14253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r4 = JS function, literals array 14263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r3 = literal index 14273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r2 = RegExp pattern 14283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r1 = RegExp flags 1429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // r0 = RegExp literal clone 143080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 143180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); 14323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 143380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r5, FieldMemOperand(r4, literal_offset)); 14353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(r5, ip); 1437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(ne, &materialized); 143880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Create regexp literal using runtime function. 144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Result will be in r0. 14413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); 14423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(expr->pattern())); 14433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r1, Operand(expr->flags())); 14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r4, r3, r2, r1); 14453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r5, r0); 144780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1448bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&materialized); 1449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label allocated, runtime_allocate; 1451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); 1452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&allocated); 1453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&runtime_allocate); 1455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r5); 1456bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(r0, Operand(Smi::FromInt(size))); 1457bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(r0); 1458bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ pop(r5); 146080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&allocated); 1462bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // After this, registers are used as follows: 1463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // r0: Newly allocated regexp. 1464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // r5: Materialized regexp. 1465bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // r2: temp. 1466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CopyFields(r0, r5, r2.bit(), size / kPointerSize); 14670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) { 14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expression == NULL) { 14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, Heap::kNullValueRootIndex); 14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(expression); 14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_properties = expr->constant_properties(); 14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 14856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(constant_properties)); 148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int flags = expr->fast_elements() 148944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kFastElements 149044f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 149144f0eee88ff00398ff7f715fab053374d808c90dSteve Block flags |= expr->has_function() 149244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kHasFunction 149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 149444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r0, Operand(Smi::FromInt(flags))); 14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r3, r2, r1, r0); 14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int properties_count = constant_properties->length() / 2; 1497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->depth() > 1) { 14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (flags != ObjectLiteral::kFastElements || 15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 150185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4); 15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowObjectStub stub(properties_count); 15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 1505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1508e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in r0. 1509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 15113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Mark all computed expressions that are bound to a key that 15123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // is shadowed by a later occurrence of the same key. For the 15133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // marked expressions, no store code is emitted. 15143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu expr->CalculateEmitStore(); 15153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorTable accessor_table(isolate()->zone()); 1517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Save result on stack 1525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::CONSTANT: 1529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); 1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (key->handle()->IsSymbol()) { 15353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForAccumulatorValue(value); 1537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(r2, Operand(key->handle())); 1538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r1, MemOperand(sp)); 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, key->id()); 1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(key->id(), NO_REGISTERS); 1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForEffect(value); 15463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Fall through. 1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::PROTOTYPE: 1551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Duplicate receiver on stack. 1552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(sp)); 1553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 15540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 15550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 15563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r0, Operand(Smi::FromInt(NONE))); // PropertyAttributes 1558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r0); 1559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallRuntime(Runtime::kSetProperty, 4); 15603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 15613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ Drop(3); 15623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::GETTER: 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch accessor_table.lookup(key)->second->getter = value; 15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::SETTER: 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch accessor_table.lookup(key)->second->setter = value; 1569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Emit code to define accessors, using only a single call to the runtime for 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // each pair of corresponding getters and setters. 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (AccessorTable::Iterator it = accessor_table.begin(); 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch it != accessor_table.end(); 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++it) { 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(sp)); // Duplicate receiver. 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(it->first); 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->getter); 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->setter); 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(Smi::FromInt(NONE))); 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5); 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 158844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (expr->has_function()) { 158944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result_saved); 159044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r0, MemOperand(sp)); 159144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(r0); 159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallRuntime(Runtime::kToFastProperties, 1); 159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 159444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 15960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 15980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1603d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 16043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_elements = expr->constant_elements(); 16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(2, constant_elements->length()); 16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind constant_elements_kind = 16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_fast_elements = constant_elements_kind == FAST_ELEMENTS; 16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArrayBase> constant_elements_values( 16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase::cast(constant_elements->get(1))); 1615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 16163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 16173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 16183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(constant_elements)); 16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r3, r2, r1); 16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (has_fast_elements && constant_elements_values->map() == 162244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->heap()->fixed_cow_array_map()) { 1623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub stub( 1624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); 1625756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 162644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter( 162744f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2); 1628756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (expr->depth() > 1) { 1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1630756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 1631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 1632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(constant_elements_kind == FAST_ELEMENTS || 16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch constant_elements_kind == FAST_SMI_ONLY_ELEMENTS || 16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FLAG_smi_only_arrays); 16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowArrayStub::Mode mode = has_fast_elements 16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? FastCloneShallowArrayStub::CLONE_ELEMENTS 16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; 16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowArrayStub stub(mode, length); 1640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 16413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 16443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 16463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 16483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 16493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 16503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 16513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (subexpr->AsLiteral() != NULL || 16523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block CompileTimeValue::IsCompileTimeValue(subexpr)) { 16533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block continue; 16543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 16573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 16583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 16593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 16613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (constant_elements_kind == FAST_ELEMENTS) { 16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = FixedArray::kHeaderSize + (i * kPointerSize); 16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r6, MemOperand(sp)); // Copy of array literal. 16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset)); 16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(result_register(), FieldMemOperand(r1, offset)); 16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier for the array store. 16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(r1, offset, result_register(), r2, 16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, kDontSaveFPRegs, 16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); 16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp)); // Copy of array literal. 16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset)); 16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(Smi::FromInt(i))); 16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r4, Operand(Smi::FromInt(expr->literal_index()))); 16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StoreArrayLiteralElementStub stub; 16773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 16783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 16813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 16840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 16860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 16873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // on the left-hand side. 1695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->target()->IsValidLeftHandSide()) { 1696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->target()); 1697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1700402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 17013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 1702402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 170480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 170580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (property != NULL) { 170680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen assign_type = (property->key()->IsPropertyName()) 170780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? NAMED_PROPERTY 170880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : KEYED_PROPERTY; 1709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // We need the receiver both on the stack and in the accumulator. 17190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(property->obj()); 1720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(result_register()); 1721402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 17220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1724402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1725402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 172625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (expr->is_compound()) { 17273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 17283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(property->key()); 172925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); 173025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 173125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 17323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 17333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->key()); 173425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 1735402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1736402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 17388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // For compound assignments we need another deoptimization point after the 17398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // variable/property load. 1740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 17410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 17420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 17430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 17443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->target()->AsVariableProxy()); 17458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailout(expr->target(), TOS_REG); 17460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 17470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 17480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 17498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); 17500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 17510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 17520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 17538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); 17540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 17550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1756402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1757402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 175880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 1759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r0); // Left operand goes on the stack. 1760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForAccumulatorValue(expr->value()); 1761402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 176280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 176380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? OVERWRITE_RIGHT 176480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : NO_OVERWRITE; 176580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position() + 1); 17660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 176780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitInlineSmiBinaryOp(expr->binary_operation(), 176980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 177080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mode, 177180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 1772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch expr->value()); 177380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 1774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBinaryOp(expr->binary_operation(), op, mode); 177580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Deoptimization point in case the binary operation may have side effects. 1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailout(expr->binary_operation(), TOS_REG); 177980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 17800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1781402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1782402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1784402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1785402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1786402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1787402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1788402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 17900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen expr->op()); 1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 1793402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1794402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1795402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1796402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1797402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1798402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1799402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1800402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1801402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1802402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1803402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1805e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 1806e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 1807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(key->handle())); 1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call load IC. It has arguments receiver and property name r0 and r2. 180944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); 1811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1814d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 181625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Call keyed load IC. It has arguments key and receiver in r0 and r1. 181744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 18183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); 1819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 182380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 182480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 1825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Expression* left_expr, 1826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Expression* right_expr) { 1827e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label done, smi_case, stub_call; 1828e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1829e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register scratch1 = r2; 1830e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register scratch2 = r3; 1831e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get the arguments. 1833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register left = r1; 1834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register right = r0; 1835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ pop(left); 1836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Perform combined smi check on both operands. 1838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ orr(scratch1, left, Operand(right)); 1839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JumpPatchSite patch_site(masm_); 1841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch patch_site.EmitJumpIfSmi(scratch1, &smi_case); 1842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&stub_call); 1844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(op, mode); 18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 18463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 1847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&done); 1848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&smi_case); 1850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Smi case. This code works the same way as the smi-smi case in the type 1851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // recording binary operation stub, see 1852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // BinaryOpStub::GenerateSmiSmiOperation for comments. 1853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch switch (op) { 1854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SAR: 1855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&stub_call); 1856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ GetLeastBitsFromSmi(scratch1, right, 5); 1857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, Operand(left, ASR, scratch1)); 1858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bic(right, right, Operand(kSmiTagMask)); 1859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SHL: { 1861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&stub_call); 1862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(scratch1, left); 1863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ GetLeastBitsFromSmi(scratch2, right, 5); 1864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(scratch1, Operand(scratch1, LSL, scratch2)); 1865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(scratch2, scratch1, Operand(0x40000000), SetCC); 1866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(mi, &stub_call); 1867e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiTag(right, scratch1); 1868e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1870e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SHR: { 1871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&stub_call); 1872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(scratch1, left); 1873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ GetLeastBitsFromSmi(scratch2, right, 5); 1874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(scratch1, Operand(scratch1, LSR, scratch2)); 1875e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(scratch1, Operand(0xc0000000)); 1876e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &stub_call); 1877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiTag(right, scratch1); 1878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1879e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::ADD: 1881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(scratch1, left, Operand(right), SetCC); 1882e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &stub_call); 1883e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, scratch1); 1884e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1885e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SUB: 1886e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ sub(scratch1, left, Operand(right), SetCC); 1887e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &stub_call); 1888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, scratch1); 1889e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1890e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::MUL: { 1891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(ip, right); 1892e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ smull(scratch1, scratch2, left, ip); 1893e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(ip, Operand(scratch1, ASR, 31)); 1894e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(ip, Operand(scratch2)); 1895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &stub_call); 18963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(scratch1, Operand(0)); 1897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, Operand(scratch1), LeaveCC, ne); 1898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &done); 1899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(scratch2, right, Operand(left), SetCC); 1900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl); 1901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(mi, &stub_call); 1902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_OR: 1905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ orr(right, left, Operand(right)); 1906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_AND: 1908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ and_(right, left, Operand(right)); 1909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_XOR: 1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ eor(right, left, Operand(right)); 1912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch default: 1914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 1915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 1918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 191980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 192080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 192180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Token::Value op, 192480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode) { 1925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(op, mode); 19273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 19293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) { 1935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw 1936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ReferenceError' on the left-hand side. 1937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->IsValidLeftHandSide()) { 1938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr); 1939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 19433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 1944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 1946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 1949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 1950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 1951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1954f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 19560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 19570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(var, Token::ASSIGN); 1958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 19620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 1963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); // Restore value. 1965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic); 1970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 19743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 19753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(prop->key()); 19763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r1, r0); 19773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(r2); 1978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); // Restore value. 19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->KeyedStoreIC_Initialize() 19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 19823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic); 1983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 1987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 19910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::Value op) { 1992589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 1993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Global var, const, or let. 19943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(var->name())); 19958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, GlobalObjectOperand()); 19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 2000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (op == Token::INIT_CONST) { 2002589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Const initializers need a write barrier. 2003589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(!var->IsParameter()); // No const parameters. 2004589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsStackLocal()) { 2005589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label skip; 2006589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r1, StackOperand(var)); 2007589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); 2008589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(ne, &skip); 2009589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(result_register(), StackOperand(var)); 2010589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&skip); 2011589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 2012589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsContextSlot() || var->IsLookupSlot()); 2013589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Like var declarations, const declarations are hoisted to function 2014589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // scope. However, unlike var initializers, const initializers are 2015589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // able to drill a hole to that function context, even from inside a 2016589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 'with' context. We thus bypass the normal static scope lookup for 2017589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // var->IsContextSlot(). 2018589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(r0); 2019589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r0, Operand(var->name())); 2020589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r0); // Context and name. 2021589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == LET && op != Token::INIT_LET) { 2025589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Non-initializing assignment to let variable needs a write barrier. 2026589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsLookupSlot()) { 2027589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(r0); // Value. 2028589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r1, Operand(var->name())); 20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(Smi::FromInt(language_mode()))); 2030589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r1, r0); // Context, name, strict mode. 2031589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kStoreContextSlot, 4); 2032589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 2033589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2034589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label assign; 2035589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, r1); 2036589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r3, location); 2037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); 2038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(ne, &assign); 2039589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r3, Operand(var->name())); 2040589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(r3); 2041589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 2042589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Perform the assignment. 2043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&assign); 2044589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(result_register(), location); 2045589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 204669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // RecordWrite may destroy all its register arguments. 204769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(r3, result_register()); 2048589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = Context::SlotOffset(var->index()); 20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot( 20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); 205169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 205269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 205369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 20543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { 20553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assignment to var or initializing assignment to let/const 20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in harmony mode. 2057589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsStackAllocated() || var->IsContextSlot()) { 2058589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, r1); 2059589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (FLAG_debug_code && op == Token::INIT_LET) { 2060589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Check for an uninitialized let binding. 2061589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r2, location); 2062589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); 2063589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Check(eq, "Let binding re-initialization."); 20643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2065589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Perform the assignment. 2066589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(r0, location); 2067589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 2068589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r3, r0); 20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = Context::SlotOffset(var->index()); 20703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot( 20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); 2072589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2073589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 2074589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(var->IsLookupSlot()); 2075589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(r0); // Value. 2076589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r1, Operand(var->name())); 20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(Smi::FromInt(language_mode()))); 2078589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r1, r0); // Context, name, strict mode. 2079589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kStoreContextSlot, 4); 20803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 20813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2082589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Non-initializing assignments to consts are ignored. 20833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 20843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 20853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2086d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2087d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 2088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 2089d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop != NULL); 2090d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(prop->key()->AsLiteral() != NULL); 20913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 2093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 2094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 2095d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 2096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 2097e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value. 2098d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 2099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 2100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 2101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 2104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 2105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 2106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load receiver to r1. Leave a copy in the stack if needed for turning the 2107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // receiver into fast case. 2108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->ends_initialization_block()) { 2109402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp)); 2110402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 2111402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(r1); 2112402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 2113402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 21153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 21163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 21173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 2118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 2120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 2121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Result of assignment, saved even if not needed. 2122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Receiver is under the result value. 2123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); 2124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 2125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 2126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 2127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Drop(1); 2128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2134d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 2136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment starts a block of assignments to the same object, 2138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // change to slow case to avoid the quadratic behavior of repeatedly 2139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // adding fast properties. 2140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->starts_initialization_block()) { 2141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 2142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Receiver is now under the key and value. 2143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); 2144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 2145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToSlowProperties, 1); 2146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 2147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 2150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 2151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 2152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load receiver to r2. Leave a copy in the stack if needed for turning the 2153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // receiver into fast case. 2154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->ends_initialization_block()) { 2155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp)); 2156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); 2158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->KeyedStoreIC_Initialize() 21623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 2164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the assignment ends an initialization block, revert to fast case. 2166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->ends_initialization_block()) { 2167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Result of assignment, saved even if not needed. 2168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Receiver is under the result value. 2169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(ip, MemOperand(sp, kPointerSize)); 2170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(ip); 2171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kToFastProperties, 1); 2172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ pop(r0); 2173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Drop(1); 2174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 2181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 2182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 2183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 21850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->obj()); 2186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(expr); 2187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 21890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->obj()); 21900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->key()); 219125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ pop(r1); 2192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 2193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::CallIC(Handle<Code> code, 21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::Mode rmode, 22003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned ast_id) { 22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ic_total_count_++; 22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Call(code, rmode, ast_id); 22033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2205d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitCallWithIC(Call* expr, 2206402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Object> name, 2207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::Mode mode) { 2208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the IC. 2209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 22103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 2211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 22123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 22133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 22143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 22153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ mov(r2, Operand(name)); 22163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 2218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 22193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the IC initialization code. 222044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = 2221589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); 22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, mode, expr->id()); 2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordJSReturnSite(expr); 2224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 2225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 22260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 22309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Expression* key) { 22328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the key. 22338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(key); 22348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 22358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Swap the name of the function and the receiver on the stack to follow 22368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // the calling convention for call ICs. 22378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(r1); 22388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(r0); 22398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(r1); 22408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 22419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Code common for calls using the IC. 22429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ZoneList<Expression*>* args = expr->arguments(); 22439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen int arg_count = args->length(); 2244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 22453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 22463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 22473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 22489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 22499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Record source position for debugger. 2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 22519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Call the IC initialization code. 225244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = 2253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); 22548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. 22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 2256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordJSReturnSite(expr); 22579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Restore context register. 22589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 22598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang context()->DropAndPlug(1, r0); // Drop the key still on the stack. 22609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 22619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 22629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { 2264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Code common for calls using the call stub. 2265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 22683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 22693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 22703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Record source position for debugger. 2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 2274589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CallFunctionStub stub(arg_count, flags); 22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 2277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordJSReturnSite(expr); 22783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 22793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 22800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 2281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push copy of the first argument or undefined if it doesn't exist. 2286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (arg_count > 0) { 2287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 2288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 2290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r1); 2292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the receiver of the enclosing function. 22943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int receiver_offset = 2 + info_->scope()->num_parameters(); 22953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize)); 2296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r1); 22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the language mode. 22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(language_mode()))); 2299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r1); 2300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the start position of the scope the calls resides in. 23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); 23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the runtime call. 23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); 2307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 2311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 2312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We want to verify that RecordJSReturnSite gets called on all paths 2313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // through this function. Avoid early returns. 2314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->return_is_recorded_ = false; 2315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 2316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 2318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Expression* callee = expr->expression(); 2319589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = callee->AsVariableProxy(); 2320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Property* property = callee->AsProperty(); 2321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL && proxy->var()->is_possibly_eval()) { 2323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // In a call to eval, we first call %ResolvePossiblyDirectEval to 2324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // resolve the function we need to call and the receiver of the 2325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. Then we call the resolved function using the given 2326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 2327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 2328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 2329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope pos_scope(masm()->positions_recorder()); 2331589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(callee); 23323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 23333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(r2); // Reserved receiver slot. 2334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 23353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push the arguments. 23363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 23373e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 23383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 23393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 2340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Push a copy of the function (found below the arguments) and 2341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // resolve eval. 2342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 23431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(r1); 23443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitResolvePossiblyDirectEval(arg_count); 23453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 23463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // The runtime call returns a pair of values in r0 (function) and 23473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // r1 (receiver). Touch up the stack with the right values. 23483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); 23493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ str(r1, MemOperand(sp, arg_count * kPointerSize)); 23503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 2353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 2354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT); 23553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordJSReturnSite(expr); 2358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 2359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 23600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 2361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL && proxy->var()->IsUnallocated()) { 2362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push global object as receiver for the call IC. 23638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, GlobalObjectOperand()); 2364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r0); 2365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); 2366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 236759151504615d929945dc59db37bf1166937748c6Steve Block // Call to a lookup slot (dynamically introduced variable). 236859151504615d929945dc59db37bf1166937748c6Steve Block Label slow, done; 236959151504615d929945dc59db37bf1166937748c6Steve Block 2370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 23713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Generate code for loading from variables potentially shadowed 23723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // by eval-introduced variables. 2373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 23743e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 237559151504615d929945dc59db37bf1166937748c6Steve Block 237659151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 23770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Call the runtime to find the function to call (returned in r0) 237859151504615d929945dc59db37bf1166937748c6Steve Block // and the object holding it (returned in edx). 2379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(context_register()); 2380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r2, Operand(proxy->name())); 2381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r2); 2382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLoadContextSlot, 2); 238359151504615d929945dc59db37bf1166937748c6Steve Block __ Push(r0, r1); // Function, receiver. 238459151504615d929945dc59db37bf1166937748c6Steve Block 238559151504615d929945dc59db37bf1166937748c6Steve Block // If fast case code has been generated, emit code to push the 238659151504615d929945dc59db37bf1166937748c6Steve Block // function and receiver and have the slow path jump around this 238759151504615d929945dc59db37bf1166937748c6Steve Block // code. 238859151504615d929945dc59db37bf1166937748c6Steve Block if (done.is_linked()) { 238959151504615d929945dc59db37bf1166937748c6Steve Block Label call; 239059151504615d929945dc59db37bf1166937748c6Steve Block __ b(&call); 239159151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 239259151504615d929945dc59db37bf1166937748c6Steve Block // Push function. 239359151504615d929945dc59db37bf1166937748c6Steve Block __ push(r0); 23943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The receiver is implicitly the global receiver. Indicate this 23953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // by passing the hole to the call function stub. 23963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); 239759151504615d929945dc59db37bf1166937748c6Steve Block __ push(r1); 239859151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&call); 239959151504615d929945dc59db37bf1166937748c6Steve Block } 240059151504615d929945dc59db37bf1166937748c6Steve Block 2401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The receiver is either the global receiver or an object found 2402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // by LoadContextSlot. That object could be the hole if the 2403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // receiver is implicitly the global object. 2404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); 2405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (property != NULL) { 2406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->obj()); 2408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (property->key()->IsPropertyName()) { 2410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitCallWithIC(expr, 2411589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch property->key()->AsLiteral()->handle(), 2412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch RelocInfo::CODE_TARGET); 2413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitKeyedCallWithIC(expr, property->key()); 2415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 24163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Call to an arbitrary expression not handled specially above. 2418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2419589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(callee); 24203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load global receiver object. 24228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, GlobalObjectOperand()); 2423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 2424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r1); 2425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 2426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 24273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // RecordJSReturnSite should have been called. 2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(expr->return_is_recorded_); 2432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 24333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 24343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 24353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2436d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 2437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 2438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 2439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 2440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 244180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 244280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 244380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 244480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 24450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->expression()); 2446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 2448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 24510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 2452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 2455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 2456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 2457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 245880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into r1 and r0. 2459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(arg_count)); 246080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 2461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 24623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record call targets in unoptimized code, but not in the snapshot. 24633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallFunctionFlags flags; 24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!Serializer::enabled()) { 24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags = RECORD_CALL_TARGET; 24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> uninitialized = 24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TypeFeedbackCells::UninitializedSentinel(isolate()); 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell(uninitialized); 24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordTypeFeedbackCell(expr->id(), cell); 24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(cell)); 24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags = NO_CALL_FUNCTION_FLAGS; 24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallConstructStub stub(flags); 24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); 24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 24790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 249280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 24930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 24940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ tst(r0, Operand(kSmiTagMask)); 2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Split(eq, if_true, if_false, fall_through); 2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { 25053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 251380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 251980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) { 25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 253480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 253780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 25381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kNullValueRootIndex); 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 2542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 2543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 2544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 2545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 2546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_false); 2547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 25483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, if_false); 25503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 255280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(le, if_true, if_false, fall_through); 2553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2557f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { 25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 25603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(args->length() == 1); 25613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 25620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 25633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 25643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 25653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 25663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 256780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 25703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 25711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 25723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 25733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 257480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(ge, if_true, if_false, fall_through); 25753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 25760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 25773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 25783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 25793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { 25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 258980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 259880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(ne, if_true, if_false, fall_through); 2599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2604756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime* expr) { 26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2607756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ASSERT(args->length() == 1); 2608756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 26090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2610756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2611756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label materialize_true, materialize_false; 2612756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_true = NULL; 2613756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_false = NULL; 261480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 26150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 26160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2617756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 26188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (FLAG_debug_code) __ AbortIfSmi(r0); 26198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 26208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 26218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset)); 26228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 26238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(ne, if_true); 26248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 26258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Check for fast case object. Generate false result for slow case object. 26268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 26278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); 26288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 26298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmp(r2, ip); 26308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(eq, if_false); 26318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 26328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Look for valueOf symbol in the descriptor array, and indicate false if 26338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // found. The type is not checked, so if it is a transition it is a false 26348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // negative. 2635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadInstanceDescriptors(r1, r4); 26368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset)); 26378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // r4: descriptor array 26388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // r3: length of descriptor array 26398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Calculate the end of the descriptor array. 26408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 26418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch STATIC_ASSERT(kSmiTagSize == 1); 26428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch STATIC_ASSERT(kPointerSize == 4); 26438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ add(r2, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 26448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); 26458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 26468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Calculate location of the first key name. 26478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ add(r4, 26488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch r4, 26498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag + 26508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DescriptorArray::kFirstIndex * kPointerSize)); 26518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Loop through all the keys in the descriptor array. If one of these is the 26528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // symbol valueOf the result is false. 26538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Label entry, loop; 26548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // The use of ip to store the valueOf symbol asumes that it is not otherwise 26558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // used in the loop below. 26568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(ip, Operand(FACTORY->value_of_symbol())); 26578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(&entry); 26588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&loop); 26598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r3, MemOperand(r4, 0)); 26608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmp(r3, ip); 26618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(eq, if_false); 26628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ add(r4, r4, Operand(kPointerSize)); 26638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&entry); 26648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmp(r4, Operand(r2)); 26658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(ne, &loop); 26668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 26678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // If a valueOf property is not found on the object check that it's 26688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // prototype is the un-modified String prototype. If not result is false. 26698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset)); 26703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r2, if_false); 26718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); 26728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r3, ContextOperand(cp, Context::GLOBAL_INDEX)); 26738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset)); 26748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 26758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmp(r2, r3); 26768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(ne, if_false); 26778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 26788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Set the bit in the map to indicate that it has been checked safe for 26798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // default valueOf and set true result. 26808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset)); 26818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 26828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset)); 26838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(if_true); 26848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 26860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2687756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 2688756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 2689756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { 26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 269980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 27000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 27010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 2704589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); 27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 270680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2707f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2709f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2711f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 272180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 27220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 27230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 272880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { 27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2736f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2737f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 274380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 27440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 27450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 2748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 275080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { 27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(expr->arguments()->length() == 0); 2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 276380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 27640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 27650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 2768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 2772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &check_frame_marker); 2775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); 2776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 2778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 2779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 2780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 278280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { 27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 2791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 27930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 27940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 2795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 279980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 28000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 28010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); 2804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); 28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 280680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) { 28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ArgumentsAccessStub expects the key in edx and the formal 28170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // parameter count in r0. 28180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 28203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 2821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2822f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 28230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2824f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 28283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(expr->arguments()->length() == 0); 2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label exit; 2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 28313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &exit); 2838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 2841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 28440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 2851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 28561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &null); 2857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 2859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assume that there are only two callable types, and one of them is at 28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // either end of the type range for JS object types. Saves extra comparisons. 28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 28633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE); 28643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Map is now in r0. 2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, &null); 28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_SPEC_OBJECT_TYPE + 1); 28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &function); 28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE)); 28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAST_SPEC_OBJECT_TYPE - 1); 28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &function); 28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assume that there is no larger type. 28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); 28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the constructor in the map is a JS function. 2878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset)); 2879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 2880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &non_function_constructor); 2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r0 now contains the constructor function. Grab the 2883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); 2885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset)); 2886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 2887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex); 2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 289569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(r0, Heap::kObject_symbolRootIndex); 2896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kNullValueRootIndex); 2901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLog(CallRuntime* expr) { 2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Conditionally generate a log call. 2911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Args: 2912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0 (literal string): The type of logging (corresponds to the flags). 2913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This is used to determine whether or not to generate the log call. 2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1 (string): Format string. Access the string at argument index 2 2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // with '%2s' (see Logger::LogRuntime for all the formats). 2916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 2 (array): Arguments to the format string. 29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 3); 2919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 29200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 29210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kLog, 2); 2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 29243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Finally, we're expected to leave a value on the top of the stack. 2926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 29270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) { 29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(expr->arguments()->length() == 0); 2933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label slow_allocate_heapnumber; 2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label heapnumber_allocated; 2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 29379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber); 2938f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&heapnumber_allocated); 2939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&slow_allocate_heapnumber); 29413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Allocate a heap number. 29423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CallRuntime(Runtime::kNumberAlloc, 0); 2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r4, Operand(r0)); 2944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&heapnumber_allocated); 2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert 32 random bits in r0 to 0.(32 random bits) in a double 2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // by computing: 2949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 29508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 29518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ PrepareCallCFunction(1, r0); 29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, ContextOperand(context_register(), Context::GLOBAL_INDEX)); 29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); 29548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); 2955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CpuFeatures::Scope scope(VFP3); 2957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x41300000 is the top half of 1.0 x 2^20 as a double. 2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Create this constant using mov/orr to avoid PC relative load. 2959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, Operand(0x41000000)); 2960f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ orr(r1, r1, Operand(0x300000)); 2961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move 0x41300000xxxxxxxx (x = random bits) to VFP. 2962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vmov(d7, r0, r1); 2963f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Move 0x4130000000000000 to VFP. 29649ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(r0, Operand(0, RelocInfo::NONE)); 2965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vmov(d8, r0, r1); 2966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Subtract and store the result in the heap number. 2967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vsub(d7, d7, d8); 2968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ sub(r0, r4, Operand(kHeapObjectTag)); 2969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ vstr(d7, r0, HeapNumber::kValueOffset); 2970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, r4); 2971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 29728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ PrepareCallCFunction(2, r0); 29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, ContextOperand(context_register(), Context::GLOBAL_INDEX)); 2974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(r4)); 29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset)); 2976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallCFunction( 29778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ExternalReference::fill_heap_number_with_random_function(isolate()), 2); 2978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) { 2985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SubStringStub stub; 29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 29890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 29900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 29910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 2992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 29930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { 2998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 2999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke RegExpExecStub stub; 30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 4); 30020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 30030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 30040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(3)); 3006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 30070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) { 30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3013f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 30140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); // Load the object. 3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 30181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &done); 3019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 3020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); 3021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 3022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 3023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 30250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) { 30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(args->length() == 2); 30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_NE(NULL, args->at(1)->AsLiteral()); 30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle())); 30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(args->at(0)); // Load the object. 30363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label runtime, done; 30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = r0; 30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = r0; 30403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0 = r9; 30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1 = r1; 30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AbortIfSmi(object); 30453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE); 30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(eq, "Trying to get date field from non-date."); 30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() == 0) { 30503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); 30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() < JSDate::kFirstUncachedField) { 30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch1, Operand(stamp)); 30553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, MemOperand(scratch1)); 30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset)); 30573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(scratch1, scratch0); 30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &runtime); 30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset + 30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kPointerSize * index->value())); 30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime); 30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(2, scratch1); 30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(index)); 30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(r0); 30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 30713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 30753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 30770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 30780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 30793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (CpuFeatures::IsSupported(VFP3)) { 30803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathPowStub stub(MathPowStub::ON_STACK); 30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kMath_pow, 2); 30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { 30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 2); 30920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Load the object. 30930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); // Load the value. 3094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // r0 = value. r1 = object. 3095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 30981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r1, &done); 3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 3101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); 3102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 3105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 3106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 3107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, r0); 31093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField( 31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); 3111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 31130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { 31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(args->length(), 1); 3120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the argument on the stack and call the stub. 31210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke NumberToStringStub stub; 3124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 31250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3127f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { 31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 31320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 31357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(r0, r1); 31367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 31377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 3138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 31407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 3141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 31430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r1); 3144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 31483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 31497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 31500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 31510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 31527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 31547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 31557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r3; 31567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 31587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 31607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 31617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 31627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 31637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 31647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 31657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 31667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 31677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 31687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 31697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 31707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 31717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 31737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 31747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 31757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 31767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 31777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 31797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the undefined value into the result register, which will 31807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 31817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 31827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 31837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 31857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 31867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 31880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 31897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 31907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { 31933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 31947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(args->length() == 2); 31950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 31960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 31977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 31987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 31997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 32003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = r3; 32017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r0; 32027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 32037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 32047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 32057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 32067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 32077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 32087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 32097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 32117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 32127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 32137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 32147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 32157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 32167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 32177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 32187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 32197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 32207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 32217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 32227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kEmptyStringRootIndex); 32237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 32247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 32257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 32267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 32277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 32287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, Operand(Smi::FromInt(0))); 32297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 32307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 32317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 32327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 32337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 32347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 32350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 3236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 32393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 32420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 32430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringAddStub stub(NO_STRING_ADD_FLAGS); 3246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 32470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 32523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 32540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 32550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke StringCompareStub stub; 3258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 32590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSin(CallRuntime* expr) { 3264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load the argument on the stack and call the stub. 3265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::SIN, 3266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::TAGGED); 32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 32690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 32710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathCos(CallRuntime* expr) { 3276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load the argument on the stack and call the stub. 3277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::COS, 3278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::TAGGED); 32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 32803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(args->length() == 1); 32813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(args->at(0)); 32823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 32833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(r0); 32843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 32853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathTan(CallRuntime* expr) { 32883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the argument on the stack and call the stub. 32893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::TAN, 32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub::TAGGED); 32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 32930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 32950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathLog(CallRuntime* expr) { 3300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load the argument on the stack and call the stub. 3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::LOG, 3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::TAGGED); 33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 1); 33050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 33070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) { 3312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the argument on the stack and call the runtime function. 33133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(args->length() == 1); 3315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForStackValue(args->at(0)); 3316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallRuntime(Runtime::kMath_sqrt, 1); 3317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 3318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { 33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() >= 2); 3324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int arg_count = args->length() - 2; // 2 ~ receiver and function. 3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < arg_count + 1; i++) { 3327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForStackValue(args->at(i)); 3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForAccumulatorValue(args->last()); // Function. 3330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for proxy. 33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label proxy, done; 33333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r0, r1, r1, JS_FUNCTION_PROXY_TYPE); 33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &proxy); 33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // InvokeFunction requires the function in r1. Move it in there. 3337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(r1, result_register()); 3338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 3339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(r1, count, CALL_FUNCTION, 3340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 3341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 33423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&proxy); 33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kCall, args->length()); 33473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RegExpConstructResultStub stub; 33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT(args->length() == 3); 33570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 33590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 3360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallStub(&stub); 33610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_EQ(2, args->length()); 3368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 3370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 337244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->global_context()->jsfunction_result_caches()); 3373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 3374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Abort("Attempt to use undefined cache."); 3375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 33760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = r0; 3383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = r1; 338459151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(cache, ContextOperand(cp, Context::GLOBAL_INDEX)); 3385f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset)); 338659151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, 3388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3390f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, not_found; 3392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // tmp now holds finger offset as a smi. 339369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset)); 3395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r2 now holds finger offset as a smi. 3396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r3 now points to the start of fixed array elements. 3398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex)); 3399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Note side effect of PreIndex: r3 now points to the key of the pair. 3400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(key, r2); 3401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, ¬_found); 3402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r3, kPointerSize)); 3404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 3405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 3407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 3408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cache, key); 3409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 3410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 34120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { 34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3418bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT_EQ(2, args->length()); 3419bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3420bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register right = r0; 3421bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register left = r1; 3422bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp = r2; 3423bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp2 = r3; 3424bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 34250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 34260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3427bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ pop(left); 3428bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3429bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label done, fail, ok; 3430bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(left, Operand(right)); 3431bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(eq, &ok); 3432bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Fail if either is a non-HeapObject. 3433bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ and_(tmp, left, Operand(right)); 34343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(tmp, &fail); 3435bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset)); 3436bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset)); 3437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(tmp2, Operand(JS_REGEXP_TYPE)); 3438bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(ne, &fail); 3439bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 3440bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(tmp, Operand(tmp2)); 3441bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(ne, &fail); 3442bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset)); 3443bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset)); 3444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ cmp(tmp, tmp2); 3445bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(eq, &ok); 3446bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&fail); 3447bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ LoadRoot(r0, Heap::kFalseValueRootIndex); 3448bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&done); 3449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&ok); 3450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ LoadRoot(r0, Heap::kTrueValueRootIndex); 3451bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&done); 3452bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 34530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch} 3455bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 3456bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 34573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 34583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 34590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 346080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 346180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 346280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 346380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 346480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 34650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 34660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 346780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 346880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 346980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); 34703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Split(eq, if_true, if_false, fall_through); 347280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 34730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 347480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 347580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 347680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 34773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { 34783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 347980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(args->length() == 1); 34800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) { 3483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AbortIfNotString(r0); 3484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 348680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 348780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(r0, r0); 3488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 34890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 349080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 349180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 349280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 34933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { 3494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label bailout, done, one_char_separator, long_separator, 3495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch non_trivial_array, not_size_one_array, loop, 3496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch empty_separator_loop, one_char_separator_loop, 3497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch one_char_separator_loop_entry, long_separator_loop; 34983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(args->length() == 2); 3500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForStackValue(args->at(1)); 3501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForAccumulatorValue(args->at(0)); 3502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // All aliases of the same register have disjoint lifetimes. 3504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register array = r0; 3505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register elements = no_reg; // Will be r0. 3506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = no_reg; // Will be r0. 3507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register separator = r1; 3508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register array_length = r2; 3509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result_pos = no_reg; // Will be r2 3510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string_length = r3; 3511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string = r4; 3512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register element = r5; 3513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register elements_end = r6; 3514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register scratch1 = r7; 3515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register scratch2 = r9; 3516e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Separator operand is on the stack. 3518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ pop(separator); 3519e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check that the array is a JSArray. 3521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(array, &bailout); 3522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE); 3523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &bailout); 3524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check that the array has fast elements. 35263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CheckFastElements(scratch1, scratch2, &bailout); 3527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the array has length zero, return the empty string. 3529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset)); 3530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(array_length, SetCC); 3531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &non_trivial_array); 3532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(r0, Heap::kEmptyStringRootIndex); 3533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 3534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&non_trivial_array); 3536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get the FixedArray containing array's elements. 3538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements = array; 3539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset)); 3540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch array = no_reg; // End of array's live range. 3541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check that all array elements are sequential ASCII strings, and 3543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // accumulate the sum of their lengths, as a smi-encoded value. 3544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(string_length, Operand(0)); 3545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(element, 3546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); 3548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Loop condition: while (element < elements_end). 3549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 3550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements: Fixed array of strings. 3551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // array_length: Length of the fixed array of strings (not smi) 3552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // separator: Separator string 3553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // string_length: Accumulated sum of string lengths (smi). 3554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: Current array element. 3555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements_end: Array end. 3556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) { 3557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(array_length, Operand(0)); 3558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin"); 3559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&loop); 3561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(string, &bailout); 3563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); 3564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); 3566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(scratch1, FieldMemOperand(string, SeqAsciiString::kLengthOffset)); 3567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(string_length, string_length, Operand(scratch1)); 3568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &bailout); 3569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(element, elements_end); 3570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(lt, &loop); 3571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If array_length is 1, return elements[0], a string. 3573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(array_length, Operand(1)); 3574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, ¬_size_one_array); 3575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); 3576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 3577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(¬_size_one_array); 3579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 3581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // separator: Separator string 3582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // array_length: Length of the array. 3583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // string_length: Sum of string lengths (smi). 3584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements: FixedArray of strings. 3585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check that the separator is a flat ASCII string. 3587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(separator, &bailout); 3588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); 3589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); 3591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Add (separator length times array_length) - separator length to the 3593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // string_length to get the length of the result string. array_length is not 3594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // smi but the other values are, so the result is a smi 3595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset)); 3596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ sub(string_length, string_length, Operand(scratch1)); 3597e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ smull(scratch2, ip, array_length, scratch1); 3598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are 3599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // zero. 3600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(ip, Operand(0)); 3601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &bailout); 3602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(scratch2, Operand(0x80000000)); 3603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &bailout); 3604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(string_length, string_length, Operand(scratch2)); 3605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &bailout); 3606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 3607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get first element in the array to free up the elements register to be used 3609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // for the result. 3610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(element, 3611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch result = elements; // End of live range for elements. 3613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements = no_reg; 3614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 3615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: First array element 3616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // separator: Separator string 3617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // string_length: Length of result string (not smi) 3618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // array_length: Length of the array. 3619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AllocateAsciiString(result, 3620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch string_length, 3621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scratch1, 3622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scratch2, 3623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements_end, 3624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch &bailout); 3625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Prepare for looping. Set up elements_end to end of the array. Set 3626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result_pos to the position of the result where to write the first 3627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // character. 3628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); 3629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch result_pos = array_length; // End of live range for array_length. 3630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch array_length = no_reg; 3631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(result_pos, 3632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch result, 3633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check the length of the separator. 3636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset)); 3637e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(scratch1, Operand(Smi::FromInt(1))); 3638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(eq, &one_char_separator); 3639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(gt, &long_separator); 3640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Empty separator case 3642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&empty_separator_loop); 3643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 3644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result_pos: the position to which we are currently copying characters. 3645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: Current array element. 3646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements_end: Array end. 3647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy next array element to the result. 3649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 3651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 3652e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CopyBytes(string, result_pos, string_length, scratch1); 3654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(element, elements_end); 3655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(lt, &empty_separator_loop); // End while (element < elements_end). 3656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result.is(r0)); 3657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 3658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3659e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // One-character separator case 3660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&one_char_separator); 36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Replace separator with its ASCII character value. 3662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldrb(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize)); 3663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Jump into the loop after the code that copies the separator, so the first 3664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element is not preceded by a separator 3665e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&one_char_separator_loop_entry); 3666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&one_char_separator_loop); 3668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 3669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result_pos: the position to which we are currently copying characters. 3670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: Current array element. 3671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements_end: Array end. 36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // separator: Single separator ASCII char (in lower byte). 3673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy the separator character to the result. 3675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ strb(separator, MemOperand(result_pos, 1, PostIndex)); 3676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy next array element to the result. 3678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&one_char_separator_loop_entry); 3679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 3681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 3682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CopyBytes(string, result_pos, string_length, scratch1); 3684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(element, elements_end); 3685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(lt, &one_char_separator_loop); // End while (element < elements_end). 3686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result.is(r0)); 3687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 3688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Long separator case (separator is more than one character). Entry is at the 3690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // label long_separator below. 3691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&long_separator_loop); 3692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 3693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result_pos: the position to which we are currently copying characters. 3694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: Current array element. 3695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements_end: Array end. 3696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // separator: Separator string. 3697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy the separator to the result. 3699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset)); 3700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 3701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(string, 3702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch separator, 3703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CopyBytes(string, result_pos, string_length, scratch1); 3705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&long_separator); 3707e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 3709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 3710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CopyBytes(string, result_pos, string_length, scratch1); 3712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(element, elements_end); 3713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(lt, &long_separator_loop); // End while (element < elements_end). 3714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result.is(r0)); 3715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 3716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&bailout); 37188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 3719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 37208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang context()->Plug(r0); 37218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 37228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 37238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 3724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3725f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<String> name = expr->name(); 3726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (name->length() > 0 && name->Get(0) == '_') { 3727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 3728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 3729f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3730f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3731f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 37323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 37333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 37343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 3736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Prepare for calling JS runtime function. 37378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, GlobalObjectOperand()); 3738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); 3739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r0); 3740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 37413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 37423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the arguments ("left-to-right"). 37433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int arg_count = args->length(); 37443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < arg_count; i++) { 37450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 3746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 3749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the JS runtime function. 3750402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r2, Operand(expr->name())); 3751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 375244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = 3753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); 37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, mode, expr->id()); 3755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 3756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 3758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the C runtime function. 3759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 3760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 37610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3765d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 3767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 3768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3769589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Property* property = expr->expression()->AsProperty(); 3770589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 3771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3772589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (property != NULL) { 3773589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->obj()); 3774589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->key()); 37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) 37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? kNonStrictMode : kStrictMode; 37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(strict_mode_flag))); 377869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(r1); 377969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 378069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(r0); 3781589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 3782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 3783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Delete of an unqualified identifier is disallowed in strict mode 3784589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // but "delete this" is allowed. 37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); 3786589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 3787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r2, GlobalObjectOperand()); 3788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r1, Operand(var->name())); 3789e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r0, Operand(Smi::FromInt(kNonStrictMode))); 3790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(r2, r1, r0); 3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 3793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (var->IsStackAllocated() || var->IsContextSlot()) { 3794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-global, non-dynamic variables is false. 3795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression does not have side effects. 3796589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(var->is_this()); 3797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Non-global variable. Call the runtime to try to delete from the 3799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // context where the variable was introduced. 3800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(context_register()); 3801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r2, Operand(var->name())); 3802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r2); 3803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallRuntime(Runtime::kDeleteContextSlot, 2); 3804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 3805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 38061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-property, non-variable reference is true. 3808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression may have side effects. 3809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 3810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(true); 3811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 3813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 3816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 3817e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 38180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Heap::kUndefinedValueRootIndex); 3819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 3823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3824e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (context()->IsEffect()) { 3825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Unary NOT has no side effects so it's only necessary to visit the 3826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // subexpression. Match the optimizing compiler by not branching. 3827e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context()->IsTest()) { 38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const TestContext* test = TestContext::cast(context()); 38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The labels are swapped for the recursive call. 38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->false_label(), 38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->true_label(), 38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->fall_through()); 38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(test->true_label(), test->false_label()); 3836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We handle value contexts explicitly rather than simply visiting 38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for control and plugging the control flow into the context, 38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // because we need to prepare a pair of extra administrative AST ids 38403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for the optimizing compiler. 38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); 38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false, done; 38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_false, 38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true, 38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true); 38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_true); 38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); 38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kTrueValueRootIndex); 38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsStackValue()) __ push(r0); 38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_false); 38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); 38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kFalseValueRootIndex); 38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsStackValue()) __ push(r0); 38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 3857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 3862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 38630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { StackValueContext context(this); 38640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 38650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 38670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 38693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3871d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke case Token::ADD: { 3872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Comment cmt(masm_, "[ UnaryOperation (ADD)"); 38730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->expression()); 3874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 38753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(result_register(), &no_conversion); 38761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ToNumberStub convert_stub; 38771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallStub(&convert_stub); 3878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 38790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result_register()); 3880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke break; 3881d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 3882d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: 3884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitUnaryOperation(expr, "[ UnaryOperation (SUB)"); 38854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 38864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 3887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_NOT: 3888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)"); 38894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke break; 38904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 3891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 38933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr, 3898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* comment) { 3899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO(svenpanne): Allowing format strings in Comment would be nice here... 3900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Comment cmt(masm_, comment); 3901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 3902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UnaryOverwriteMode overwrite = 3903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 3904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UnaryOpStub stub(expr->op(), overwrite); 3905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // UnaryOpStub expects the argument to be in the 3906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // accumulator register r0. 3907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForAccumulatorValue(expr->expression()); 3908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SetSourcePosition(expr->position()); 39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); 3910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context()->Plug(r0); 3911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3914d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 3915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CountOperation"); 391680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 391780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 3919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // as the left-hand side. 3920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!expr->expression()->IsValidLeftHandSide()) { 3921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitForEffect(expr->expression()); 3922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 39263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 3927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 3929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 3930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 3931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 3932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 3933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 3934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 3938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 3939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 39400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 39413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->expression()->AsVariableProxy()); 39423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 3943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 39440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 3945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ip, Operand(Smi::FromInt(0))); 3946e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ip); 3947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 3949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Put the object both on the stack and in the accumulator. 39500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 3951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 3952e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 3953e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 39543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 39553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(prop->key()); 395625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(r1, MemOperand(sp, 0)); 395725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ push(r0); 3958e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 3959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We need a second deoptimization point after loading the value 3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // in case evaluating the property load my have a side effect. 39648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (assign_type == VARIABLE) { 39658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailout(expr->expression(), TOS_REG); 39668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 39678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailoutForId(expr->CountId(), TOS_REG); 39688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3970d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call ToNumber only if operand is not a smi. 3971d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label no_conversion; 39721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &no_conversion); 39731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ToNumberStub convert_stub; 39741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallStub(&convert_stub); 3975d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&no_conversion); 3976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 3978e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 39790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 39800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 39810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 39820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 39830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 39840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 39850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(r0); 39860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 39870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 39880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(r0, MemOperand(sp, kPointerSize)); 39890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 39900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 39910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(r0, MemOperand(sp, 2 * kPointerSize)); 39920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 39930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3997d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3998d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Inline smi case if we are in a loop. 3999d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Label stub_call, done; 4000e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JumpPatchSite patch_site(masm_); 4001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 400210e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu int count_value = expr->op() == Token::INC ? 1 : -1; 400380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(expr->op())) { 400410e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); 4005d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ b(vs, &stub_call); 4006d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // We could eliminate this smi check if we split the code at 4007d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // the first smi check before calling ToNumber. 4008e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch patch_site.EmitJumpIfSmi(r0, &done); 4009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&stub_call); 4011d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Call stub. Undo operation first. 401210e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ sub(r0, r0, Operand(Smi::FromInt(count_value))); 4013d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 401410e7c6c7845a8d467bf3fd61a215dfedd8554e21Andrei Popescu __ mov(r1, Operand(Smi::FromInt(count_value))); 4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Record position before stub call. 4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(Token::ADD, NO_OVERWRITE); 40203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); 40213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 4022d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 4023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in r0. 4025e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 4026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 4027e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 40280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 40290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 40300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 4031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context.Plug(r0); 40330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 40340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For all contexts except EffectConstant We have the result on 4035e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 40360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 40370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 4040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 40410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 4044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 4047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 4048402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(r1); 40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->StoreIC_Initialize() 40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->StoreIC_Initialize_Strict(); 40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 4053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4054e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 40550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 40560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 40590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 4064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // Key. 4065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r2); // Receiver. 40663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = is_classic_mode() 40673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? isolate()->builtins()->KeyedStoreIC_Initialize() 40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 4070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 40720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 40730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 40760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 40803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 40813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 40823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 40833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 40840d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 40850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsEffect()); 40860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!context()->IsTest()); 408780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VariableProxy* proxy = expr->AsVariableProxy(); 4088589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL && proxy->var()->IsUnallocated()) { 408980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Comment cmnt(masm_, "Global variable"); 40908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, GlobalObjectOperand()); 409180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(r2, Operand(proxy->name())); 409244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 409380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Use a regular load, not a contextual load, to avoid a reference 409480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // error. 40953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic); 4096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailout(expr, TOS_REG); 40970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4098589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 409959151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 410059151504615d929945dc59db37bf1166937748c6Steve Block 410159151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 410259151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 4103589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 410459151504615d929945dc59db37bf1166937748c6Steve Block 410559151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 410680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(r0, Operand(proxy->name())); 410780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Push(cp, r0); 410880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailout(expr, TOS_REG); 411059151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 411159151504615d929945dc59db37bf1166937748c6Steve Block 41120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 411380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 411480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // This expression cannot throw a reference error at the top level. 41153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitInDuplicateContext(expr); 4116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 4118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 41193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 41203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 41213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 41223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> check) { 41233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false; 41243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_true = NULL; 41253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_false = NULL; 41263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fall_through = NULL; 41273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 41283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &if_true, &if_false, &fall_through); 41293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 41313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForTypeofValue(sub_expr); 41320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 41333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 413544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (check->Equals(isolate()->heap()->number_symbol())) { 4136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_true); 413780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 413880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 413980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, ip); 414080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 414144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->string_symbol())) { 4142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 414380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 4144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); 4145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ge, if_false); 414680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(eq, if_true, if_false, fall_through); 414944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->boolean_symbol())) { 4150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(r0, Heap::kTrueValueRootIndex); 4151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 4152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(r0, Heap::kFalseValueRootIndex); 415380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 415469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (FLAG_harmony_typeof && 415569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch check->Equals(isolate()->heap()->null_symbol())) { 415669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(r0, Heap::kNullValueRootIndex); 415769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Split(eq, if_true, if_false, fall_through); 415844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->undefined_symbol())) { 4159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); 4160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 4161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 416280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 416380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 416480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(ne, if_true, if_false, fall_through); 4167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 416844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->function_symbol())) { 4169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 41703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE); 41723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, if_true); 41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE)); 41743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Split(eq, if_true, if_false, fall_through); 417544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (check->Equals(isolate()->heap()->object_symbol())) { 4176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 417769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (!FLAG_harmony_typeof) { 417869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(r0, Heap::kNullValueRootIndex); 417969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(eq, if_true); 418069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 418180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for JS objects => true. 41823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 41833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(lt, if_false); 41843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 41853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(gt, if_false); 4186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check for undetectable objects => false. 4187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(eq, if_true, if_false, fall_through); 419080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 419180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 4192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(if_true, if_false); 4194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 4195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 4198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 419980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 4200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First we try a fast inlined version of the compare when one of 42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the operands is a literal. 42033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryLiteralCompare(expr)) return; 42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 4206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 4207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 4208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 4209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 421080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 42110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 42120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 421380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 42143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Token::Value op = expr->op(); 42150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 421680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 4217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 42180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 4219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 4221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTrueValueRootIndex); 4222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r0, ip); 422380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 4224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 42270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 4228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InstanceofStub stub(InstanceofStub::kNoFlags); 4229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 423180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns 0 for true. 4232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ tst(r0, r0); 423380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 4234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 42380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 42391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition cond = eq; 424080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 4241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::EQ_STRICT: 424280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::EQ: 42431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block cond = eq; 4244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LT: 42461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block cond = lt; 4247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GT: 42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cond = gt; 4250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::LTE: 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cond = le; 4253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::GTE: 42551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block cond = ge; 4256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::IN: 4258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: 4259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 4260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 4261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r1); 4263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 42640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 42651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 42660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 426780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 426880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ orr(r2, r0, Operand(r1)); 42691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block patch_site.EmitJumpIfNotSmi(r2, &slow_case); 427080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, r0); 42711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Split(cond, if_true, if_false, NULL); 427280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 427380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 42741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 42751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position and call the compare IC. 42761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetSourcePosition(expr->position()); 42771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Code> ic = CompareIC::GetUninitialized(op); 42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 42793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 42811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(r0, Operand(0)); 42821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Split(cond, if_true, if_false, fall_through); 42833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 42843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 42853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 4287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 42880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 4289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 42903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NilValue nil) { 429580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 429680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 429780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 429880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 42990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 43000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 430180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(sub_expr); 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex nil_value = nil == kNullValue ? 43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kNullValueRootIndex : 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kUndefinedValueRootIndex; 43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, nil_value); 430880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, r1); 43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->op() == Token::EQ_STRICT) { 431080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 431180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex other_nil_value = nil == kNullValue ? 43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kUndefinedValueRootIndex : 43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kNullValueRootIndex; 431580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_true); 43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, other_nil_value); 431780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, r1); 431880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(eq, if_true); 43193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r0, if_false); 432080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // It can be an undetectable object. 432180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 432280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 432380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 432480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 432580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 432680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 43270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 432880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 432980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 433080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 4331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 43330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 43370d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 43380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return r0; 43390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 43420d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 43430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return cp; 43440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 43450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 43460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 4349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(value, MemOperand(fp, frame_offset)); 4350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 43513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 435459151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(dst, ContextOperand(cp, context_index)); 43553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 43563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 43583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 43593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Scope* declaration_scope = scope()->DeclarationScope(); 43603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (declaration_scope->is_global_scope()) { 43613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Contexts nested in the global context have a canonical empty function 43623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // as their closure, not the anonymous closure containing the global 43633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Pass a smi sentinel and let the runtime look up the empty 43643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // function. 43653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ip, Operand(Smi::FromInt(0))); 43663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (declaration_scope->is_eval_scope()) { 43673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Contexts created by a call to eval have the same closure as the 43683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // context calling eval, not the anonymous closure containing the eval 43693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Fetch it from the context. 43703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX)); 43713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 43723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(declaration_scope->is_function_scope()); 43733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 43743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 43753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(ip); 43763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 43773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 4380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 4381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 4383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(r1)); 4384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 4385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 4386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address in link register to stack (smi encoded Code* delta) 4387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(r1, lr, Operand(masm_->CodeObject())); 4388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 438969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 4390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(r1, r1, Operand(r1)); // Convert to smi. 4391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r1); 4392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 4396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(!result_register().is(r1)); 4397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 4398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 4399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address and return. 4400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 4401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 4402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 4403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(pc, r1, Operand(masm_->CodeObject())); 4404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __ 4408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 440969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm()) 441069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 441169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 441269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int* stack_depth, 441369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int* context_length) { 441469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // The macros used here must preserve the result register. 441569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 441669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Because the handler block contains the context of the finally 441769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // code, we can restore it directly from there for the finally code 441869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // rather than iteratively unwinding contexts via their previous 441969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // links. 442069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Drop(*stack_depth); // Down to the handler block. 442169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (*context_length > 0) { 442269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Restore the context to its dedicated register and the stack. 442369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset)); 442469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 442569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 442669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ PopTryHandler(); 442769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bl(finally_entry_); 442869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 442969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch *stack_depth = 0; 443069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch *context_length = 0; 443169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return previous_; 443269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 443369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 443469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 443569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __ 443669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 44373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 4438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 4440