13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/full-codegen/full-codegen.h" 8f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/ast/compile-time-value.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 13f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compilation-info.h" 14f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler.h" 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/code-stubs-arm.h" 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/macro-assembler-arm.h" 209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 24109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define __ ACCESS_MASM(masm()) 251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// A patch site is a location in the code which it is possible to patch. This 271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// class has a number of methods to emit the code which is patchable and the 281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// method EmitPatchInfo to record a marker back to the patchable code. This 291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit 301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// immediate value is used) is the delta from the pc to the first instruction of 311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// the patchable code. 321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED { 331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block info_emitted_ = false; 371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ~JumpPatchSite() { 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(patch_site_.is_bound() == info_emitted_); 421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When initially emitting this ensure that a jump is always generated to skip 451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the inlined smi code. 461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitJumpIfNotSmi(Register reg, Label* target) { 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!patch_site_.is_bound() && !info_emitted_); 48db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(reg, Operand(reg)); 511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, target); // Always taken before patched. 521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When initially emitting this ensure that a jump is never generated to skip 551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the inlined smi code. 561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitJumpIfSmi(Register reg, Label* target) { 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!patch_site_.is_bound() && !info_emitted_); 58db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(reg, Operand(reg)); 611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, target); // Never taken before patched. 621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitPatchInfo() { 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block literal pool emission whilst recording patch site information. 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (patch_site_.is_bound()) { 683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); 693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register reg; 703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch reg.set_code(delta_to_patch_site / kOff12Mask); 713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask); 721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info_emitted_ = true; 741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(); // Signals no inlined code. 773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 81109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MacroAssembler* masm() { return masm_; } 821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block MacroAssembler* masm_; 831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label patch_site_; 841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool info_emitted_; 861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}; 881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right. The actual 923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the 933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function. 943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// o r1: the JS function object being called (i.e., ourselves) 97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o r3: the new target value 983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o cp: our context 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o pp: our caller's constant pool pointer (if enabled) 1003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o fp: our caller's frame pointer 1013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o sp: stack pointer 1023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o lr: return address 1033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 1043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 1053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout. 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() { 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompilationInfo* info = info_; 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch profiling_counter_ = isolate()->factory()->NewCell( 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetFunctionPosition(literal()); 1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 1123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm_); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) { 1163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int receiver_offset = info->scope()->num_parameters() * kPointerSize; 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, MemOperand(sp, receiver_offset)); 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertNotSmi(r2); 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r2, r2, no_reg, FIRST_JS_RECEIVER_TYPE); 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Assert(ge, kSloppyFunctionExpectsJSReceiverReceiver); 121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the frame (that is done below). 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->set_prologue_offset(masm_->pc_offset()); 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Prologue(info->GeneratePreagedPrologue()); 1303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Increment invocation count for the function. 132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment cmnt(masm_, "[ Increment invocation count"); 134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); 135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ ldr(r2, FieldMemOperand(r2, LiteralsArray::kFeedbackVectorOffset)); 136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ ldr(r9, FieldMemOperand(r2, TypeFeedbackVector::kInvocationCountIndex * 137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch kPointerSize + 138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch TypeFeedbackVector::kHeaderSize)); 139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(r9, r9, Operand(Smi::FromInt(1))); 140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ str(r9, FieldMemOperand(r2, TypeFeedbackVector::kInvocationCountIndex * 141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch kPointerSize + 142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch TypeFeedbackVector::kHeaderSize)); 143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int locals_count = info->scope()->num_stack_slots(); 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generators allocate locals, if any, in context slots. 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); 149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(locals_count); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count > 0) { 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= 128) { 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r9, sp, Operand(locals_count * kPointerSize)); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r9, Operand(r2)); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(hs, &ok); 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r9, Heap::kUndefinedValueRootIndex); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= kMaxPushes) { 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int loop_iterations = locals_count / kMaxPushes; 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(loop_iterations)); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop_header; 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop_header); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do pushes. 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < kMaxPushes; i++) { 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r9); 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Continue loop if not done. 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r2, r2, Operand(1), SetCC); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&loop_header, ne); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int remaining = locals_count % kMaxPushes; 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the remaining pushes. 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < remaining; i++) { 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r9); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 181756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool function_in_register_r1 = true; 1844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 186f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (info->scope()->NeedsContext()) { 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument to NewContext is the function, which is still in r1. 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Allocate context"); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool need_write_barrier = true; 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->is_script_scope()) { 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 193f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(info->scope()->scope_info()); 194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNewScriptContext); 195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::ScriptContext(), 196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The new target value is not used, clobbering is safe. 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_NULL(info->scope()->new_target_var()); 199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->new_target_var() != nullptr) { 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(r3); // Preserve new target. 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (slots <= FastNewFunctionContextStub::kMaximumSlots) { 204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FastNewFunctionContextStub stub(isolate()); 205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(FastNewFunctionContextDescriptor::SlotsRegister(), 206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Operand(slots)); 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallStub(&stub); 208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Result of FastNewFunctionContextStub is always in new space. 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch need_write_barrier = false; 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(r1); 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext); 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->new_target_var() != nullptr) { 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(r3); // Preserve new target. 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 217756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch function_in_register_r1 = false; 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Context is returned in r0. It replaces the context passed to us. 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's saved in the stack and kept live in cp. 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(cp, r0); 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); 223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy any necessary parameters into the context. 2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int first_parameter = info->scope()->has_this_declaration() ? -1 : 0; 226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = first_parameter; i < num_parameters; i++) { 227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* var = 228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i); 229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 230756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int parameter_offset = StandardFrameConstants::kCallerSPOffset + 231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick (num_parameters - 1 - i) * kPointerSize; 232756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load parameter from stack. 233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ ldr(r0, MemOperand(fp, parameter_offset)); 234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand target = ContextMemOperand(cp, var->index()); 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, target); 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier. 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_write_barrier) { 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ RecordWriteContextSlot(cp, target.offset(), r0, r2, 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch kLRHasBeenSaved, kDontSaveFPRegs); 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInNewSpace(cp, r0, &done); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kExpectedNewSpaceObject); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 250756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Register holding this function and new target are both trashed in case we 253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // bailout here. But since that can happen only when new target is not used 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // and we allocate a context, the value of |function_in_register| is correct. 255bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::FunctionContext(), 256bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Possibly set up a local binding to the this function which is used in 259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // derived constructors with super calls. 260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* this_function_var = info->scope()->this_function_var(); 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (this_function_var != nullptr) { 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Comment cmnt(masm_, "[ This function"); 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!function_in_register_r1) { 264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The write barrier clobbers register again, keep it marked as such. 266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetVar(this_function_var, r1, r0, r2); 268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Possibly set up a local binding to the new target value. 271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* new_target_var = info->scope()->new_target_var(); 272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (new_target_var != nullptr) { 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Comment cmnt(masm_, "[ new.target"); 274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetVar(new_target_var, r3, r0, r2); 275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Possibly allocate RestParameters 278f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Variable* rest_param = info->scope()->rest_parameter(); 279f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (rest_param != nullptr) { 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Comment cmnt(masm_, "[ Allocate rest parameter array"); 281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!function_in_register_r1) { 282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 284109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FastNewRestParameterStub stub(isolate()); 285f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch __ CallStub(&stub); 286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch function_in_register_r1 = false; 287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetVar(rest_param, r0, r1, r2); 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* arguments = info->scope()->arguments(); 291756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (arguments != NULL) { 292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Function uses arguments object. 293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate arguments object"); 294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!function_in_register_r1) { 295756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load this again, if it's used by the local context below. 296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (is_strict(language_mode()) || !has_simple_parameters()) { 299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FastNewStrictArgumentsStub stub(isolate()); 300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallStub(&stub); 301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (literal()->has_duplicate_parameters()) { 302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r1); 303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kNewSloppyArguments_Generic); 304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FastNewSloppyArgumentsStub stub(isolate()); 306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallStub(&stub); 307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 309589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SetVar(arguments, r0, r1, r2); 310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace) { 313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kTraceEnter); 314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Visit the declarations and body. 317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::FunctionEntry(), 318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 3193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment cmnt(masm_, "[ Declarations"); 3213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch VisitDeclarations(scope()->declarations()); 3223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Assert that the declarations do not use ICs. Otherwise the debugger 3253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // won't be able to redirect a PC at an IC to the correct IC in newly 3263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // recompiled code. 3273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(0, ic_total_count_); 3283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 3293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Comment cmnt(masm_, "[ Stack check"); 331bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::Declarations(), 332bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 3333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label ok; 3343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadRoot(ip, Heap::kStackLimitRootIndex); 3353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ cmp(sp, Operand(ip)); 3363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ b(hs, &ok); 3373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Handle<Code> stack_check = isolate()->builtins()->StackCheck(); 3383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch PredictableCodeSizeScope predictable(masm_); 3393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch predictable.ExpectSize( 3403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch masm_->CallSize(stack_check, RelocInfo::CODE_TARGET)); 3413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Call(stack_check, RelocInfo::CODE_TARGET); 3423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&ok); 3433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Comment cmnt(masm_, "[ Body"); 3473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(loop_depth() == 0); 3483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch VisitStatements(literal()->body()); 3493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(loop_depth() == 0); 3503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Always emit a 'return undefined' in case control fell off the end of 353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the body. 3543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 3553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Force emit the constant pool, so it doesn't get emitted in the middle 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the back edge table. 361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch masm()->CheckConstPool(true, false); 362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 364c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid FullCodeGenerator::ClearAccumulator() { __ mov(r0, Operand(Smi::kZero)); } 365db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(profiling_counter_)); 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r3, FieldMemOperand(r2, Cell::kValueOffset)); 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef CAN_USE_ARMV7_INSTRUCTIONS 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kProfileCounterResetSequenceLength = 5 * Assembler::kInstrSize; 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kProfileCounterResetSequenceLength = 7 * Assembler::kInstrSize; 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() { 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictable_code_size_scope( 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm_, kProfileCounterResetSequenceLength); 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label start; 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&start); 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int reset_value = FLAG_interrupt_budget; 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(profiling_counter_)); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The mov instruction above can be either 1 to 3 (for ARMv7) or 1 to 5 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instructions (for ARMv6) depending upon whether it is an extended constant 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pool - insert nop to compensate. 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int expected_instr_count = 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kProfileCounterResetSequenceLength / Assembler::kInstrSize) - 2; 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(masm_->InstructionsGeneratedSince(&start) <= expected_instr_count); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (masm_->InstructionsGeneratedSince(&start) != expected_instr_count) { 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ nop(); 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(Smi::FromInt(reset_value))); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r3, FieldMemOperand(r2, Cell::kValueOffset)); 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* back_edge_target) { 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Back edge bookkeeping"); 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block literal pools whilst emitting back edge code. 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label ok; 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(back_edge_target->is_bound()); 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int weight = Min(kMaxBackEdgeWeight, 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Max(1, distance / kCodeSizeMultiplier)); 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterDecrement(weight); 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(pl, &ok); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 418086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of this PC offset to the OSR id. This is used to find 419086aeeaae12517475c22695a200be45495516549Ben Murdoch // the AST id from the unoptimized code in order to use it as a key into 420086aeeaae12517475c22695a200be45495516549Ben Murdoch // the deoptimization input data found in the optimized code. 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordBackEdge(stmt->OsrEntryId()); 422086aeeaae12517475c22695a200be45495516549Ben Murdoch 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterReset(); 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&ok); 426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS); 427086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of the OSR id to this PC. This is used if the OSR 428086aeeaae12517475c22695a200be45495516549Ben Murdoch // entry becomes the target of a bailout. We don't expect it to be, but 429086aeeaae12517475c22695a200be45495516549Ben Murdoch // we want it to work if it is. 430bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS); 431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 433109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence( 434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bool is_tail_call) { 435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Pretend that the exit is a backwards jump to the entry. 436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int weight = 1; 437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (info_->ShouldSelfOptimize()) { 438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch weight = FLAG_interrupt_budget / FLAG_self_opt_count; 439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int distance = masm_->pc_offset(); 441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier)); 442109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterDecrement(weight); 444109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label ok; 445109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(pl, &ok); 446109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Don't need to save result register if we are going to do a tail call. 447109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!is_tail_call) { 448109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(r0); 449109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 450109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!is_tail_call) { 452109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pop(r0); 453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 454109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterReset(); 455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&ok); 456109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ b(&return_label_); 462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 4643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 4653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the return value on the stack as the parameter. 4663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Runtime::TraceExit returns its parameter in r0. 4673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kTraceExit); 4693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 470109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterHandlingForReturnSequence(false); 4713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make sure that the constant pool is not emitted inside of the return 4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // sequence. 4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { Assembler::BlockConstPoolScope block_const_pool(masm_); 475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t arg_count = info_->scope()->num_parameters() + 1; 476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t sp_delta = arg_count * kPointerSize; 477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetReturnPosition(literal()); 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(svenpanne) The code below is sometimes 4 words, sometimes 5! 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictable(masm_, -1); 480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LeaveFrame(StackFrame::JAVA_SCRIPT); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { ConstantPoolUnavailableScope constant_pool_unavailable(masm_); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(sp, sp, Operand(sp_delta)); 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Jump(lr); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid FullCodeGenerator::RestoreContext() { 490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 493589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 495589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(result_register()); 497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 513109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(result_register()); 5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (index == Heap::kUndefinedValueRootIndex || 5230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kNullValueRootIndex || 5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kFalseValueRootIndex) { 525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (index == Heap::kTrueValueRootIndex) { 527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 5303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Immediates cannot be pushed directly. 5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 548109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(result_register()); 5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 55713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) || 55813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch !lit->IsUndetectable()); 55913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) || 56013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch lit->IsFalse(isolate())) { 561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 56213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) { 563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 5668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (count > 1) codegen()->DropOperands(count - 1); 5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(reg, MemOperand(sp, 0)); 589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == materialize_false); 5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 6020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 6030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 6040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 6050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 6060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 6070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 6080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 6150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kTrueValueRootIndex); 6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kFalseValueRootIndex); 6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(ip); 6230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == true_label_); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_false == false_label_); 6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), value_root_index); 6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, value_root_index); 644109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(ip); 6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ b(true_label_); 6550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 6560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ b(false_label_); 657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 6613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition, 6623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* if_true, 66380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 66480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 6653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate()); 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, condition->test_id()); 667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(eq, if_true, if_false, fall_through); 66980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid FullCodeGenerator::Split(Condition cond, 67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 67580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 67680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 6771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(cond, if_true); 67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 6791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(NegateCondition(cond), if_false); 68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 6811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(cond, if_true); 68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(if_false); 683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 687589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) { 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated()); 689589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Offset is negative because higher indexes are at lower addresses. 690589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = -var->index() * kPointerSize; 691589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Adjust by a (parameter or local) base offset. 692589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsParameter()) { 693589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += (info_->scope()->num_parameters() + 1) * kPointerSize; 694589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 695589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += JavaScriptFrameConstants::kLocal0Offset; 696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 697589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return MemOperand(fp, offset); 698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 700e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 701589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 703589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 704589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_chain_length = scope()->ContextChainLength(var->scope()); 705589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ LoadContext(scratch, context_chain_length); 706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ContextMemOperand(scratch, var->index()); 707589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 708589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return StackOperand(var); 709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 710589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 711589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 712589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 713589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) { 714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Use destination as scratch. 715589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, dest); 716589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(dest, location); 717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var, 721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register src, 722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch0, 723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1) { 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch0.is(src)); 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch0.is(scratch1)); 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(src)); 728589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, scratch0); 729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(src, location); 7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(scratch0, 7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch location.offset(), 7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch src, 7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool should_normalize, 745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_true, 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_false) { 747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only prepare for bailouts before splits if we're in a test 748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // context. Otherwise, we let the Visit function deal with the 749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // preparation to avoid preparing with the same AST id twice. 750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!context()->IsTest()) return; 751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label skip; 753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (should_normalize) __ b(&skip); 754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr, BailoutState::TOS_REGISTER); 755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (should_normalize) { 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ LoadRoot(ip, Heap::kTrueValueRootIndex); 757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r0, ip); 758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Split(eq, if_true, if_false, NULL); 759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&skip); 760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The variable in the declaration always resides in the current function 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context. 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); 768109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we're not inside a with or catch context. 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r1, Heap::kWithContextMapRootIndex); 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(ne, kDeclarationInWithContext); 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(ne, kDeclarationInCatchContext); 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration( 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* declaration) { 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* variable = proxy->var(); 783589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (variable->location()) { 784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::UNALLOCATED: { 785bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!variable->binding_needs_init()); 786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); 787f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!slot.IsInvalid()); 788f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch globals_->Add(isolate()->factory()->undefined_value(), zone()); 790589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: 794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (variable->binding_needs_init()) { 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r0, StackOperand(variable)); 798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 79969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: 802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (variable->binding_needs_init()) { 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r0, ContextMemOperand(cp, variable->index())); 80769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // No write barrier since the_hole_value is in old space. 808bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 80969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 81069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOOKUP: { 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 814f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(VAR, variable->mode()); 815f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!variable->binding_needs_init()); 81669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(r2, Operand(variable->name())); 81713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(r2); 81813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CallRuntime(Runtime::kDeclareEvalVar); 819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 823f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 824f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration( 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionDeclaration* declaration) { 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::UNALLOCATED: { 835f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); 836f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!slot.IsInvalid()); 837f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> function = 839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_); 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for stack-overflow exception. 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (function.is_null()) return SetStackOverflow(); 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(function, zone()); 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: { 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(result_register(), StackOperand(variable)); 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: { 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(result_register(), ContextMemOperand(cp, variable->index())); 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(variable->index()); 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a function, which is not a smi. 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(cp, 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset, 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_register(), 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r2, 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 869bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOOKUP: { 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(variable->name())); 876109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r2); 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push initial value for function declaration. 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(declaration->fun()); 87913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CallRuntimeWithOperands(Runtime::kDeclareEvalFunction); 880bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 88169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 890d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 892589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r1, Operand(pairs)); 893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); 894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EmitLoadTypeFeedbackVector(r2); 895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(r1, r0, r2); 896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kDeclareGlobals); 8973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 8983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 9070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 908bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS); 909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 9178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clause->body_target()->Unuse(); 9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 9300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 93280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 0)); // Switch value. 9340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 9360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 93780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 93880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ orr(r2, r1, r0); 9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block patch_site.EmitJumpIfNotSmi(r2, &slow_case); 9401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 94180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, r0); 94280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(ne, &next_test); 94380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 9448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(clause->body_target()); 9451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow_case); 94680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 94780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 9481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position before stub call for type feedback. 949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(clause); 950109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> ic = 951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code(); 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, clause->CompareId()); 9533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&skip); 957bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(clause, BailoutState::TOS_REGISTER); 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kTrueValueRootIndex); 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, ip); 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &next_test); 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(clause->body_target()); 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip); 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand::Zero()); 966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &next_test); 967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 9688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(clause->body_target()); 969f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 971f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 974109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(1); // Switch value is no longer needed. 975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 97669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(nested_statement.break_label()); 977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 9788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(default_clause->body_target()); 979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 9858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(clause->body_target()); 986bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS); 987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 99069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(nested_statement.break_label()); 991bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS); 992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetStatementPosition(stmt, SKIP_BREAK); 998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); 1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1001109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Get the object to enumerate over. 1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionAsStatementPosition(stmt->enumerable()); 10030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 10043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch OperandStackDepthIncrement(5); 10053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 10063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label loop, exit; 10073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Iteration loop_statement(this, stmt); 10083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch increment_loop_depth(); 1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1010109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If the object is null or undefined, skip over the loop, otherwise convert 1011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // it to a JS receiver. See ECMA-262 version 5, section 12.6.4. 1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 10131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &convert); 1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r0, r1, r1, FIRST_JS_RECEIVER_TYPE); 10153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(ge, &done_convert); 1016109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r0, Heap::kNullValueRootIndex); 1017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(eq, &exit); 1018109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); 1019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(eq, &exit); 1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 1021c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET); 1022f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 1024bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER); 1025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check cache validity in generated code. If we cannot guarantee cache 1028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // validity, call the runtime system to check cache validity or get the 1029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // property names in a fixed array. Note: Proxies never have an enum cache, 1030bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // so will always take the slow path. 1031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label call_runtime; 1032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CheckEnumCache(&call_runtime); 1033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The enum cache is valid. Load the map of the object being 1035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // iterated over and use the cache for the iteration. 1036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label use_cache; 1037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 1038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&use_cache); 1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 1041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&call_runtime); 1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Duplicate the enumerable object on the stack. 1043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kForInEnumerate); 1044bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER); 1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label fixed_array; 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kMetaMapRootIndex); 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r2, ip); 1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &fixed_array); 1054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register r0. Get the enumeration cache from it. 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_descriptors; 1057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&use_cache); 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnumLength(r1, r0); 1060c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ cmp(r1, Operand(Smi::kZero)); 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &no_descriptors); 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadInstanceDescriptors(r0, r2); 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheOffset)); 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the four remaining stack slots. 1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Map. 1069c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(r0, Operand(Smi::kZero)); 1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push enumeration cache, enumeration cache length (as smi) and zero. 1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r2, r1, r0); 1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_descriptors); 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&exit); 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register r0. Iterate through that. 1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r1, Operand(Smi::FromInt(1))); // Smi(1) indicates slow check 10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(r1, r0); // Smi and array 1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); 1084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r1); // Fixed array length (as smi). 1085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS); 1086c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(r0, Operand(Smi::kZero)); 1087109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r0); // Initial index. 1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionAsStatementPosition(stmt->each()); 1092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the current count to r0, load the length to r1. 1094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); 1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); // Compare to the array length. 109669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(hs, loop_statement.break_label()); 1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Get the current entry of the array into register r0. 1099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ ldr(r0, MemOperand::PointerAddressFromSmiKey(r2, r0)); 1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the expected map from the stack or a smi in the 1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register r2. 1105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); 1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If not, we may have to filter the key. 1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label update_each; 1110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); 1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); 1112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r4, Operand(r2)); 1113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &update_each); 1114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // We need to filter the key, record slow-path here. 11163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int const vector_index = SmiFromSlot(slot)->value(); 1117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EmitLoadTypeFeedbackVector(r3); 1118109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(r2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); 1119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ str(r2, FieldMemOperand(r3, FixedArray::OffsetOfElementAt(vector_index))); 1120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // r0 contains the key. The receiver in r1 is the second argument to the 1122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // ForInFilter. ForInFilter returns undefined if the receiver doesn't 1123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // have the key or returns the name-converted key. 1124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET); 1125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 1126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER); 1127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); 112869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(eq, loop_statement.continue_label()); 1129f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 1131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // entry in register r0. 1132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 1133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { EffectContext context(this); 1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitAssignment(stmt->each(), stmt->EachFeedbackSlot()); 1137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS); 1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body(). 1141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS); 1142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 1143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 1144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the going to the next element by incrementing 1146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the index (smi) stored on top of the stack. 114769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.continue_label()); 1148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS); 1149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); 1150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r0, r0, Operand(Smi::FromInt(1))); 1151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, &loop); 1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(&loop); 1155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 115769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.break_label()); 1158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(5); 1159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 1161bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS); 1162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 11653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, 1168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FeedbackVectorSlot slot) { 1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NeedsHomeObject(initializer)); 1170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); 1171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(StoreDescriptor::ValueRegister(), 1172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand(sp, offset * kPointerSize)); 1173f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, isolate()->factory()->home_object_symbol()); 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, 1178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset, 1179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FeedbackVectorSlot slot) { 1180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NeedsHomeObject(initializer)); 1181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(StoreDescriptor::ReceiverRegister(), r0); 1182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(StoreDescriptor::ValueRegister(), 1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand(sp, offset * kPointerSize)); 1184f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, isolate()->factory()->home_object_symbol()); 1185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, 1189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeofMode typeof_mode, 1190589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register current = cp; 1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register next = r1; 1193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp = r2; 1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval(); 1196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) { 1197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!s->NeedsContext()) continue; 1198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (s->calls_sloppy_eval()) { 1199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check that extension is "the hole". 1200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); 1201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); 1202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load next context in chain. 1204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); 1205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Walk the rest of the chain without clobbering cp. 1206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch current = next; 1207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch to_check--; 1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // All extension objects were empty and it is safe to use a normal global 1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // load machinery. 1212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitGlobalVariableLoad(proxy, typeof_mode); 1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1216589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot()); 1219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = cp; 122059151504615d929945dc59db37bf1166937748c6Steve Block Register next = r3; 122159151504615d929945dc59db37bf1166937748c6Steve Block Register temp = r4; 122259151504615d929945dc59db37bf1166937748c6Steve Block 1223589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1224f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (s->NeedsContext()) { 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->calls_sloppy_eval()) { 1226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that extension is "the hole". 1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); 1228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); 122959151504615d929945dc59db37bf1166937748c6Steve Block } 1230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(next, ContextMemOperand(context, Context::PREVIOUS_INDEX)); 123159151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering cp. 1232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context = next; 123359151504615d929945dc59db37bf1166937748c6Steve Block } 123459151504615d929945dc59db37bf1166937748c6Steve Block } 1235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that last extension is "the hole". 1236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); 1237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); 1238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This function is used only for loads, not stores, so it's safe to 1240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // return an cp-based operand (the write barrier cannot be allowed to 1241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destroy the cp register). 1242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ContextMemOperand(context, var->index()); 124359151504615d929945dc59db37bf1166937748c6Steve Block} 124459151504615d929945dc59db37bf1166937748c6Steve Block 124559151504615d929945dc59db37bf1166937748c6Steve Block 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, 1247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeofMode typeof_mode, 1248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* slow, Label* done) { 124959151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast-case code for variables that might be shadowed by 125059151504615d929945dc59db37bf1166937748c6Steve Block // eval-introduced variables. Eval is used a lot without 125159151504615d929945dc59db37bf1166937748c6Steve Block // introducing variables. In those cases, we do not want to 125259151504615d929945dc59db37bf1166937748c6Steve Block // perform a runtime call for all variables in the scope 125359151504615d929945dc59db37bf1166937748c6Steve Block // containing the eval. 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = proxy->var(); 12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == DYNAMIC_GLOBAL) { 1256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); 125759151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == DYNAMIC_LOCAL) { 1259589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* local = var->local_if_not_shadowed(); 1260589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); 1261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (local->binding_needs_init()) { 1262589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 1263bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ b(ne, done); 1264bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(r0, Operand(var->name())); 1265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(r0); 1266bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 1267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 1268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(done); 126959151504615d929945dc59db37bf1166937748c6Steve Block } 127059151504615d929945dc59db37bf1166937748c6Steve Block } 127159151504615d929945dc59db37bf1166937748c6Steve Block} 127259151504615d929945dc59db37bf1166937748c6Steve Block 1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, 1274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeofMode typeof_mode) { 12753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Record position before possible IC call. 1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(proxy); 1277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); 12783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Variable* var = proxy->var(); 12793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Three cases: global variables, lookup variables, and all other types of 1281589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // variables. 1282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 1283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::UNALLOCATED: { 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Global variable"); 1285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitGlobalVariableLoad(proxy, typeof_mode); 1286589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(r0); 1287589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1288589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 128959151504615d929945dc59db37bf1166937748c6Steve Block 1290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 1291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: 1292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: { 1293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : "[ Stack variable"); 1296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { 1297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Throw a reference error when using an uninitialized let/const 1298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // binding in harmony mode. 1299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label done; 1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GetVar(r0, var); 1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 1302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ b(ne, &done); 1303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(r0, Operand(var->name())); 1304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(r0); 1305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 1306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&done); 1307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(r0); 1308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 1309589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(var); 1311589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOOKUP: { 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Lookup variable"); 1316589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label done, slow; 1317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Generate code for loading from variables potentially shadowed 1318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // by eval-introduced variables. 1319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); 1320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 1321109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(var->name()); 1322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::FunctionId function_id = 1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch typeof_mode == NOT_INSIDE_TYPEOF 1324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ? Runtime::kLoadLookupSlot 1325109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Runtime::kLoadLookupSlotInsideTypeof; 1326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(function_id); 132769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&done); 132869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(r0); 1329f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 13300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 1333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 13343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { 1339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Expression* expression = (property == NULL) ? NULL : property->value(); 13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expression == NULL) { 13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, Heap::kNullValueRootIndex); 1342109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r1); 13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(expression); 1345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (NeedsHomeObject(expression)) { 1346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(property->kind() == ObjectLiteral::Property::GETTER || 1347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch property->kind() == ObjectLiteral::Property::SETTER); 1348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3; 1349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObject(expression, offset, property->GetSlot()); 1350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_properties = expr->constant_properties(); 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(constant_properties)); 1362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int flags = expr->ComputeFlags(); 136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r0, Operand(Smi::FromInt(flags))); 1364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (MustCreateObjectLiteralWithRuntime(expr)) { 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r3, r2, r1, r0); 1366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCreateObjectLiteral); 13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); 13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 1370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER); 1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in r0. 1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorTable accessor_table(zone()); 1379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int property_index = 0; 1380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (; property_index < expr->properties()->length(); property_index++) { 1381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ObjectLiteral::Property* property = expr->properties()->at(property_index); 1382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->is_computed_name()) break; 1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Literal* key = property->key()->AsLiteral(); 1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); // Save result on stack 1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::CONSTANT: 1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 1396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // It is safe to use [[Put]] here because the boilerplate already 1399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // contains computed properties with an uninitialized value. 1400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (key->IsStringLiteral()) { 1401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(key->IsPropertyName()); 14023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForAccumulatorValue(value); 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(r0)); 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); 1406f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(property->GetSlot(0), key->value()); 1407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); 1408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (NeedsHomeObject(value)) { 1410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1)); 1411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForEffect(value); 14143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Duplicate receiver on stack. 1418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(sp)); 1419109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 14200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 14210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 14223e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (NeedsHomeObject(value)) { 1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObject(value, 2, property->GetSlot()); 1425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes 1427109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 1428109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kSetProperty); 14293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 1430109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(3); 14313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::PROTOTYPE: 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Duplicate receiver on stack. 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r0, MemOperand(sp)); 1436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(value); 1438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(property->emit_store()); 1439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kInternalSetPrototype); 1440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), 1441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::GETTER: 1445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->emit_store()) { 144613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AccessorTable::Iterator it = accessor_table.lookup(key); 144713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch it->second->bailout_id = expr->GetIdForPropertySet(property_index); 144813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch it->second->getter = property; 1449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::SETTER: 1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->emit_store()) { 145313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AccessorTable::Iterator it = accessor_table.lookup(key); 145413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch it->second->bailout_id = expr->GetIdForPropertySet(property_index); 145513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch it->second->setter = property; 1456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Emit code to define accessors, using only a single call to the runtime for 14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // each pair of corresponding getters and setters. 14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (AccessorTable::Iterator it = accessor_table.begin(); 14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch it != accessor_table.end(); 14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++it) { 14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(sp)); // Duplicate receiver. 1467109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(it->first); 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->getter); 14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->setter); 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(Smi::FromInt(NONE))); 1472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 1473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked); 147413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS); 1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Object literals have two parts. The "static" part on the left contains no 1478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // computed property names, and so we can compute its map ahead of time; see 1479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part 1480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // starts with the first computed property name, and continues with all 1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // properties to its right. All the code from above initializes the static 1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // component of the object literal, and arranges for the map of the result to 1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // reflect the static order in which the keys appear. For the dynamic 1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // properties, we compile them into a series of "SetOwnProperty" runtime 1485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // calls. This will preserve insertion order. 1486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (; property_index < expr->properties()->length(); property_index++) { 1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ObjectLiteral::Property* property = expr->properties()->at(property_index); 1488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Expression* value = property->value(); 1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!result_saved) { 1491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); // Save result on the stack 1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result_saved = true; 1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r0, MemOperand(sp)); // Duplicate receiver. 1496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { 1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!property->is_computed_name()); 1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(value); 1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(property->emit_store()); 1502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kInternalSetPrototype); 1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), 1504bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitPropertyKey(property, expr->GetIdForPropertyName(property_index)); 1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(value); 1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (NeedsHomeObject(value)) { 1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObject(value, 2, property->GetSlot()); 1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch switch (property->kind()) { 1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case ObjectLiteral::Property::CONSTANT: 1514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case ObjectLiteral::Property::COMPUTED: 1516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->emit_store()) { 1517109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(NONE)); 1518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(property->NeedsSetFunctionName())); 1519109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral); 152013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), 152113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch BailoutState::NO_REGISTERS); 1522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(3); 1524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 1526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case ObjectLiteral::Property::PROTOTYPE: 1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch UNREACHABLE(); 1529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 1530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case ObjectLiteral::Property::GETTER: 1532109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(NONE)); 1533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked); 1534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 1535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case ObjectLiteral::Property::SETTER: 1537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(NONE)); 1538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked); 1539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 1540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 15450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 15470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 15483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 15503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 15533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_elements = expr->constant_elements(); 1556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool has_fast_elements = 1557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IsFastObjectElementsKind(expr->constant_elements_kind()); 15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArrayBase> constant_elements_values( 15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase::cast(constant_elements->get(1))); 1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (has_fast_elements && !FLAG_allocation_site_pretenuring) { 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the only customer of allocation sites is transitioning, then 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we can turn it off if we don't have anywhere else to transition to. 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 15693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(constant_elements)); 1571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (MustCreateArrayLiteralWithRuntime(expr)) { 1572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r0, Operand(Smi::FromInt(expr->ComputeFlags()))); 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r3, r2, r1, r0); 1574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCreateArrayLiteral); 1575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); 1577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1578f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch RestoreContext(); 15793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1580bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER); 15813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 1583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* subexprs = expr->values(); 1584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int length = subexprs->length(); 15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1588f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch for (int array_index = 0; array_index < length; array_index++) { 1589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Expression* subexpr = subexprs->at(array_index); 1590109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!subexpr->IsSpread()); 1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 15923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 15933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 15953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 1597109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 15983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 15993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 16013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(StoreDescriptor::NameRegister(), Operand(Smi::FromInt(array_index))); 1603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 1604f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->LiteralFeedbackSlot()); 1605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->GetIdForElement(array_index), 1607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 16083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 16110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 16130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 16143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 162380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 1624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(property); 1625402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1626402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1629402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1631402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1632402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need the receiver both on the stack and in the register. 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 1636402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 16370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1639402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_SUPER_PROPERTY: 1641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue( 1642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch property->obj()->AsSuperPropertyReference()->this_var()); 1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue( 1644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch property->obj()->AsSuperPropertyReference()->home_object()); 1645109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 1646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (expr->is_compound()) { 1647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r1; 1648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, kPointerSize)); 1649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 1650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 1651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 1654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue( 1655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch property->obj()->AsSuperPropertyReference()->this_var()); 1656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue( 1657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch property->obj()->AsSuperPropertyReference()->home_object()); 1658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForAccumulatorValue(property->key()); 1659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 1660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (expr->is_compound()) { 1661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r1; 1662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, 2 * kPointerSize)); 1663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 1664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, 2 * kPointerSize)); 1665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 1666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 1667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 167025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (expr->is_compound()) { 16713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(sp, 1 * kPointerSize)); 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0)); 167625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 16773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 16783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->key()); 167925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 1680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1681402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1682402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 16838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // For compound assignments we need another deoptimization point after the 16848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // variable/property load. 1685402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 16860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 16870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 16880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 16893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->target()->AsVariableProxy()); 1690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER); 16910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 16920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 16930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 1694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(property->LoadId(), 1695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 16960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 1697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_SUPER_PROPERTY: 1698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitNamedSuperPropertyLoad(property); 1699bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(property->LoadId(), 1700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 1701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 1703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitKeyedSuperPropertyLoad(property); 1704bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(property->LoadId(), 1705bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 1706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 17070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 17080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 1709bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(property->LoadId(), 1710bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 17110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 17120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 171580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 1716109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); // Left operand goes on the stack. 1717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForAccumulatorValue(expr->value()); 1718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 17190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 172080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitInlineSmiBinaryOp(expr->binary_operation(), 172280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 172380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 1724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch expr->value()); 172580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 1726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitBinaryOp(expr->binary_operation(), op); 172780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Deoptimization point in case the binary operation may have side effects. 1730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER); 173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 17320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1733402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1734402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(expr); 1736402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1739c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case VARIABLE: { 1740c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->target()->AsVariableProxy(); 1741c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), 1742c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 1743bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 1745402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1746c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1748402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1749402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_SUPER_PROPERTY: 1751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitNamedSuperPropertyStore(property); 1752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier context()->Plug(r0); 1753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 1755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitKeyedSuperPropertyStore(property); 1756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier context()->Plug(r0); 1757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1758402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1759402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1760402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1761402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1762402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1763402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1764402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) { 1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Yield"); 1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(expr); 1768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Evaluate yielded value first; the initial iterator definition depends on 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this. It stays on the stack while we update the iterator. 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->expression()); 1772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label suspend, continuation, post_runtime, resume, exception; 17743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 17753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ jmp(&suspend); 17763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&continuation); 1777bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // When we arrive here, r0 holds the generator object. 17783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ RecordGeneratorContinuation(); 1779bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ ldr(r1, FieldMemOperand(r0, JSGeneratorObject::kResumeModeOffset)); 178013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ ldr(r0, FieldMemOperand(r0, JSGeneratorObject::kInputOrDebugPosOffset)); 1781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); 1782bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); 1783bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::kReturn))); 1784bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ b(lt, &resume); 1785bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(result_register()); 1786bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ b(gt, &exception); 17873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch EmitCreateIteratorResult(true); 17883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch EmitUnwindAndReturn(); 17893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 1790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&exception); 1791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(expr->rethrow_on_exception() ? Runtime::kReThrow 1792f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch : Runtime::kThrow); 1793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 17943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&suspend); 17953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch OperandStackDepthIncrement(1); // Not popped on this path. 17963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch VisitForAccumulatorValue(expr->generator_object()); 17973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); 17983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ mov(r1, Operand(Smi::FromInt(continuation.pos()))); 17993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); 18003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); 18013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ mov(r1, cp); 18023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, 18033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch kLRHasBeenSaved, kDontSaveFPRegs); 18043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); 18053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ cmp(sp, r1); 18063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ b(eq, &post_runtime); 18073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ push(r0); // generator object 18083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 1809bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 18103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&post_runtime); 18113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch PopOperand(result_register()); 18123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch EmitReturnSequence(); 1813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 18143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&resume); 18153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch context()->Plug(result_register()); 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1818109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PushOperands(Register reg1, Register reg2) { 1819109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(2); 1820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(reg1, reg2); 1821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 1822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PopOperands(Register reg1, Register reg2) { 1824109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(2); 1825109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(reg1, reg2); 1826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 1827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1828109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitOperandStackDepthCheck() { 1829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 1830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + 1831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch operand_stack_depth_ * kPointerSize; 1832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ sub(r0, fp, sp); 1833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(r0, Operand(expected_diff)); 1834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kUnexpectedStackDepth); 1835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) { 1839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label allocate, done_allocate; 1840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1841bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &allocate, 1842bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&done_allocate); 1844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&allocate); 1846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(Smi::FromInt(JSIteratorResult::kSize)); 1847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace); 1848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_allocate); 1850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1); 18513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch PopOperand(r2); 1852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r3, 1853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); 1854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 1858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset)); 1859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset)); 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op, 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* left_expr, 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* right_expr) { 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, smi_case, stub_call; 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1 = r2; 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2 = r3; 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the arguments. 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left = r1; 1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register right = r0; 1875109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(left); 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform combined smi check on both operands. 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orr(scratch1, left, Operand(right)); 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfSmi(scratch1, &smi_case); 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stub_call); 1884109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&smi_case); 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi case. This code works the same way as the smi-smi case in the type 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // recording binary operation stub, see 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SAR: 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ GetLeastBitsFromSmi(scratch1, right, 5); 1895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, Operand(left, ASR, scratch1)); 1896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bic(right, right, Operand(kSmiTagMask)); 1897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SHL: { 1899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(scratch1, left); 1900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ GetLeastBitsFromSmi(scratch2, right, 5); 1901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(scratch1, Operand(scratch1, LSL, scratch2)); 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TrySmiTag(right, scratch1, &stub_call); 1903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SHR: { 1906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(scratch1, left); 1907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ GetLeastBitsFromSmi(scratch2, right, 5); 1908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(scratch1, Operand(scratch1, LSR, scratch2)); 1909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(scratch1, Operand(0xc0000000)); 1910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &stub_call); 1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiTag(right, scratch1); 1912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::ADD: 1915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(scratch1, left, Operand(right), SetCC); 1916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &stub_call); 1917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, scratch1); 1918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1919e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SUB: 1920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ sub(scratch1, left, Operand(right), SetCC); 1921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &stub_call); 1922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, scratch1); 1923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1924e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::MUL: { 1925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(ip, right); 1926e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ smull(scratch1, scratch2, left, ip); 1927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(ip, Operand(scratch1, ASR, 31)); 1928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(ip, Operand(scratch2)); 1929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &stub_call); 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch1, Operand::Zero()); 1931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, Operand(scratch1), LeaveCC, ne); 1932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &done); 1933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(scratch2, right, Operand(left), SetCC); 1934c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(right, Operand(Smi::kZero), LeaveCC, pl); 1935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(mi, &stub_call); 1936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_OR: 1939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ orr(right, left, Operand(right)); 1940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_AND: 1942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ and_(right, left, Operand(right)); 1943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_XOR: 1945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ eor(right, left, Operand(right)); 1946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch default: 1948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 1949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 1952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 195380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 195480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 195580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { 1957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < lit->properties()->length(); i++) { 1958f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ClassLiteral::Property* property = lit->properties()->at(i); 1959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Expression* value = property->value(); 1960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1961109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch = r1; 1962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (property->is_static()) { 1963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, kPointerSize)); // constructor 1964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, 0)); // prototype 1966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1967109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitPropertyKey(property, lit->GetIdForProperty(i)); 1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The static prototype property is read only. We handle the non computed 1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // property name case in the parser. Since this is the only case where we 1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // need to check for an own read only property we special case this so we do 1973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // not need to do this for every property. 1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->is_static() && property->is_computed_name()) { 1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowIfStaticPrototype); 1976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(r0); 1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1979958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(value); 1980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (NeedsHomeObject(value)) { 1981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObject(value, 2, property->GetSlot()); 1982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1983958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (property->kind()) { 1985f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case ClassLiteral::Property::METHOD: 1986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(DONT_ENUM)); 1987109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(property->NeedsSetFunctionName())); 1988109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral); 1989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1991f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case ClassLiteral::Property::GETTER: 1992109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(DONT_ENUM)); 1993109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked); 1994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1996f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case ClassLiteral::Property::SETTER: 1997109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(DONT_ENUM)); 1998109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked); 1999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2001f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch case ClassLiteral::Property::FIELD: 2002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier default: 2003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 2004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { 2010109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(r1); 2011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); 20123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 20143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 20150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2018e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr, 2020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FeedbackVectorSlot slot) { 2021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->IsValidReferenceExpressionOrThis()); 2022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(prop); 2025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 2028c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->AsVariableProxy(); 20290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 2030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, 2031c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 2032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 2035109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); // Preserve value. 20360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::ReceiverRegister(), r0); 2038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ValueRegister()); // Restore value. 2039f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, prop->key()->AsLiteral()->value()); 2040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_SUPER_PROPERTY: { 2043109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); 2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue( 2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prop->obj()->AsSuperPropertyReference()->home_object()); 2047958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stack: value, this; r0: home_object 2048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = r2; 2049958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2 = r3; 2050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(scratch, result_register()); // home_object 2051958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(r0, MemOperand(sp, kPointerSize)); // value 2052958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch2, MemOperand(sp, 0)); // this 2053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(scratch2, MemOperand(sp, kPointerSize)); // this 2054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(scratch, MemOperand(sp, 0)); // home_object 2055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stack: this, home_object; r0: value 2056958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitNamedSuperPropertyStore(prop); 2057958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2058958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2059958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: { 2060109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); 2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue( 2063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prop->obj()->AsSuperPropertyReference()->home_object()); 2064958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForAccumulatorValue(prop->key()); 2065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = r2; 2066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2 = r3; 2067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch2, MemOperand(sp, 2 * kPointerSize)); // value 2068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stack: value, this, home_object; r0: key, r3: value 2069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, kPointerSize)); // this 2070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(scratch, MemOperand(sp, 2 * kPointerSize)); 2071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, 0)); // home_object 2072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(scratch, MemOperand(sp, kPointerSize)); 2073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(r0, MemOperand(sp, 0)); 2074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(r0, scratch2); 2075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stack: this, home_object, key; r0: value. 2076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitKeyedSuperPropertyStore(prop); 2077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 2080109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); // Preserve value. 20813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 20823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(prop->key()); 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), r0); 2084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperands(StoreDescriptor::ValueRegister(), 2085109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StoreDescriptor::ReceiverRegister()); 2086f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(slot); 2087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var, MemOperand location) { 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(result_register(), location); 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // RecordWrite may destroy all its register arguments. 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r3, result_register()); 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(var->index()); 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, 2107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FeedbackVectorSlot slot, 2108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch HoleCheckMode hole_check_mode) { 2109589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 2110589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Global var, const, or let. 2111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); 2112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, var->name()); 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { 2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!var->IsLookupSlot()); 2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand location = VarOperand(var, r1); 2118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform an initialization check for lexically declared variables. 2119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (hole_check_mode == HoleCheckMode::kRequired) { 2120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label assign; 2121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ ldr(r3, location); 2122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); 2123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ b(ne, &assign); 2124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(r3, Operand(var->name())); 2125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(r3); 2126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 2127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&assign); 2128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (var->mode() != CONST) { 2130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if (var->throw_on_const_assignment(language_mode())) { 2132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ CallRuntime(Runtime::kThrowConstAssignError); 2133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { 2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Initializing assignment to const {this} needs a write barrier. 2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label uninitialized_this; 2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand location = VarOperand(var, r1); 2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r3, location); 2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); 2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(eq, &uninitialized_this); 2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r0, Operand(var->name())); 2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(r0); 2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&uninitialized_this); 2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 2149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(var->mode() != CONST || op == Token::INIT); 2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (var->IsLookupSlot()) { 2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Assignment to var. 2152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(var->name()); 2153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(r0); 2154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(is_strict(language_mode()) 2155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ? Runtime::kStoreLookupSlot_Strict 2156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Runtime::kStoreLookupSlot_Sloppy); 2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Assignment to var or initializing assignment to let/const in harmony 2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // mode. 2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK((var->IsStackAllocated() || var->IsContextSlot())); 2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand location = VarOperand(var, r1); 2162109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { 2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check for an uninitialized let binding. 2164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r2, location); 2165589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(eq, kLetBindingReInitialization); 2167589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 21693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 21703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 21713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 21723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 21733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 2176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop != NULL); 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->key()->IsLiteral()); 2179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2180109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 2181f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value()); 2182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 2184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { 2189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Assignment to named property of super. 2190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r0 : value 2191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stack : receiver ('this'), home_object 2192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(prop != NULL); 2193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Literal* key = prop->key()->AsLiteral(); 2194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(key != NULL); 2195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2196109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(key->value()); 2197109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2198109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(is_strict(language_mode()) 2199109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ? Runtime::kStoreToSuper_Strict 2200109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Runtime::kStoreToSuper_Sloppy); 2201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { 2205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Assignment to named property of super. 2206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // r0 : value 2207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // stack : receiver ('this'), home_object, key 2208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(prop != NULL); 2209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2210109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2211109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(is_strict(language_mode()) 2212109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ? Runtime::kStoreKeyedToSuper_Strict 2213109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Runtime::kStoreKeyedToSuper_Sloppy); 2214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 2219109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperands(StoreDescriptor::ReceiverRegister(), 2220109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StoreDescriptor::NameRegister()); 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(r0)); 2222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2223f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->AssignmentSlot()); 2224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2225bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 2226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(r0); 2227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { 2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the target function. 2234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ConvertReceiverMode convert_mode; 2235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (callee->IsVariableProxy()) { 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { StackValueContext context(this); 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(callee->AsVariableProxy()); 2238bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(callee, BailoutState::NO_REGISTERS); 22393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push undefined as receiver. This is patched in the method prologue if it 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a sloppy mode method. 2242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 2243109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(ip); 2244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch convert_mode = ConvertReceiverMode::kNullOrUndefined; 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!callee->AsProperty()->IsSuperAccess()); 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(callee->AsProperty()); 2251bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), 2252bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, MemOperand(sp, 0)); 2255109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(ip); 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 2257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch convert_mode = ConvertReceiverMode::kNotNullOrUndefined; 22583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitCall(expr, convert_mode); 2261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = callee->AsProperty(); 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->IsSuperAccess()); 2269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(prop); 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!key->value()->IsSmi()); 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register scratch = r1; 2275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference(); 2276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(super_ref->home_object()); 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(super_ref->this_var()); 2278109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, kPointerSize * 2)); 2281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 2282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(key->value()); 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack here: 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - home_object 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - this (receiver) <-- LoadFromSuper will pop here and below. 2288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - home_object 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - key 2290109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kLoadFromSuper); 2291bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER); 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace home_object with target function. 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack here: 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - target function 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitCall(expr); 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* key) { 23068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the key. 23078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(key); 23088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 23108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), r0); 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(callee->AsProperty()); 2316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), 2317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, MemOperand(sp, 0)); 2321109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(ip); 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined); 23259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 23269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 23279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { 2329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Expression* callee = expr->expression(); 2330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(callee->IsProperty()); 2331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Property* prop = callee->AsProperty(); 2332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(prop->IsSuperAccess()); 2333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(prop); 2335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the function from the receiver. 2336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r1; 2337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference(); 2338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(super_ref->home_object()); 2339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForAccumulatorValue(super_ref->this_var()); 2340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, kPointerSize * 2)); 2343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 2344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->key()); 2345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stack here: 2347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - home_object 2348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - this (receiver) 2349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. 2350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - home_object 2351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - key 2352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper); 2353bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER); 2354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Replace home_object with target function. 2356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(r0, MemOperand(sp, kPointerSize)); 2357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stack here: 2359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - target function 2360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // - this (receiver) 2361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitCall(expr); 2362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) { 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments. 2367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arg_count; i++) { 2370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(i)); 2371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS); 23743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch SetCallPosition(expr, expr->tail_call_mode()); 2375109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (expr->tail_call_mode() == TailCallMode::kAllow) { 2376109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_trace) { 2377109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kTraceTailCall); 2378109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2379109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Update profiling counters before the tail call since we will 2380109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // not return to this function. 2381109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterHandlingForReturnSequence(true); 2382109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2383c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Code> code = 2384c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CodeFactory::CallIC(isolate(), mode, expr->tail_call_mode()).code(); 2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot()))); 23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2387c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(r0, Operand(arg_count)); 2388c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallIC(code); 2389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordJSReturnSite(expr); 2392bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 23930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 2394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2396bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { 2397bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch int arg_count = expr->arguments()->length(); 2398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r4: copy of the first argument or undefined if it doesn't exist. 2399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (arg_count > 0) { 2400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r4, MemOperand(sp, arg_count * kPointerSize)); 2401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); 2403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r3: the receiver of the enclosing function. 2406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // r2: language mode. 2409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r2, Operand(Smi::FromInt(language_mode()))); 2410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r1: the start position of the scope the calls resides in. 24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); 24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // r0: the source position of the eval call. 2415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(r0, Operand(Smi::FromInt(expr->position()))); 2416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 24173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the runtime call. 2418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(r4, r3, r2, r1, r0); 2419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kResolvePossiblyDirectEval); 2420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. 2424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { 2425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VariableProxy* callee = expr->expression()->AsVariableProxy(); 2426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (callee->var()->IsLookupSlot()) { 242759151504615d929945dc59db37bf1166937748c6Steve Block Label slow, done; 2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(callee); 2429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Generate code for loading from variables potentially shadowed 2430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // by eval-introduced variables. 2431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); 243259151504615d929945dc59db37bf1166937748c6Steve Block 243359151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 24340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Call the runtime to find the function to call (returned in r0) 243559151504615d929945dc59db37bf1166937748c6Steve Block // and the object holding it (returned in edx). 2436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(callee->name()); 2437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kLoadLookupSlotForCall); 2438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperands(r0, r1); // Function, receiver. 2439bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS); 244059151504615d929945dc59db37bf1166937748c6Steve Block 244159151504615d929945dc59db37bf1166937748c6Steve Block // If fast case code has been generated, emit code to push the 244259151504615d929945dc59db37bf1166937748c6Steve Block // function and receiver and have the slow path jump around this 244359151504615d929945dc59db37bf1166937748c6Steve Block // code. 244459151504615d929945dc59db37bf1166937748c6Steve Block if (done.is_linked()) { 244559151504615d929945dc59db37bf1166937748c6Steve Block Label call; 244659151504615d929945dc59db37bf1166937748c6Steve Block __ b(&call); 244759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 244859151504615d929945dc59db37bf1166937748c6Steve Block // Push function. 244959151504615d929945dc59db37bf1166937748c6Steve Block __ push(r0); 24503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The receiver is implicitly the global receiver. Indicate this 24513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // by passing the hole to the call function stub. 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 245359151504615d929945dc59db37bf1166937748c6Steve Block __ push(r1); 245459151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&call); 245559151504615d929945dc59db37bf1166937748c6Steve Block } 24563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(callee); 2458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // refEnv.WithBaseObject() 2459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 2460109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r2); // Reserved receiver slot. 24613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { 2466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // In a call to eval, we first call 2467bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Runtime_ResolvePossiblyDirectEval to resolve the function we need 2468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // to call. Then we call the resolved function using the given arguments. 2469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int arg_count = args->length(); 2471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PushCalleeAndWithBaseObject(expr); 2473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the arguments. 2475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arg_count; i++) { 2476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(i)); 2477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push a copy of the function (found below the arguments) and 2480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // resolve eval. 2481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(r1); 2483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch EmitResolvePossiblyDirectEval(expr); 2484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Touch up the stack with the resolved function. 2486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS); 2489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Record source position for debugger. 2491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetCallPosition(expr); 2492c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny, 2493c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch expr->tail_call_mode()) 2494c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch .code(); 2495c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot()))); 2496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r0, Operand(arg_count)); 2498c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(code, RelocInfo::CODE_TARGET); 2499109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 2500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RecordJSReturnSite(expr); 2501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 2502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->DropAndPlug(1, r0); 25033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 25043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 25053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2506d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 2507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 2508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 2509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 2510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 251180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 251280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 251380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 251480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 2515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!expr->expression()->IsSuperPropertyReference()); 2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(expr->expression()); 2517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 2519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 25220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 2523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 2526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 2527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetConstructCallPosition(expr); 2528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 252980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into r1 and r0. 2530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(arg_count)); 253180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 2532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record call targets in unoptimized code. 2534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ EmitLoadTypeFeedbackVector(r2); 2535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(r3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot()))); 2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallConstructStub stub(isolate()); 2538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallIC(stub.GetCode()); 2539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 2540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER); 2541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 25420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { 2547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SuperCallReference* super_call_ref = 2548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch expr->expression()->AsSuperCallReference(); 2549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_NOT_NULL(super_call_ref); 2550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the super constructor target on the stack (may be null, 2552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // but the Construct builtin can deal with that properly). 2553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(super_call_ref->this_function_var()); 2554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(result_register()); 2555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(result_register(), 2556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldMemOperand(result_register(), HeapObject::kMapOffset)); 2557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(result_register(), 2558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldMemOperand(result_register(), Map::kPrototypeOffset)); 2559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 2560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the arguments ("left-to-right") on the stack. 2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int arg_count = args->length(); 2564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arg_count; i++) { 2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(i)); 2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the construct call builtin that handles allocation and 2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // constructor invocation. 2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetConstructCallPosition(expr); 2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load new target into r3. 2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(super_call_ref->new_target_var()); 2574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, result_register()); 2575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load function and argument count into r1 and r0. 2577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r0, Operand(arg_count)); 2578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 2579f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 2581109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 2582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RecordJSReturnSite(expr); 2584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 2585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(r0); 2586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 25930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 259880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 26000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 260180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiTst(r0); 2604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(eq, if_true, if_false, fall_through); 2605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) { 26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 26133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 26140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 26153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 26163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 26173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 26183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 261980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 26200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 26210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 26223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 2624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r0, r1, r1, FIRST_JS_RECEIVER_TYPE); 26253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 262680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(ge, if_true, if_false, fall_through); 26273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 26280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 26293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 26303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 26313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 26323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 26333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 264180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 26420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 26430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 2646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 264880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) { 26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 266380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 2664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->PrepareTest(&materialize_true, &materialize_false, &if_true, 2665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &if_false, &fall_through); 2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 2668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r0, r1, r1, JS_TYPED_ARRAY_TYPE); 26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 267080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 26720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { 2677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ZoneList<Expression*>* args = expr->arguments(); 2678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(args->length() == 1); 2679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForAccumulatorValue(args->at(0)); 2681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label materialize_true, materialize_false; 2683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* if_true = NULL; 2684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* if_false = NULL; 2685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* fall_through = NULL; 2686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &if_true, &if_false, &fall_through); 2688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(r0, if_false); 2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 2691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(eq, if_true, if_false, fall_through); 2693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier context()->Plug(if_true, if_false); 2695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) { 2699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(args->length() == 1); 2701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(args->at(0)); 2703f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2704f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2705f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2706f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 270780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 2708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->PrepareTest(&materialize_true, &materialize_false, &if_true, 2709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &if_false, &fall_through); 2710f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(r0, if_false); 2712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r0, r1, r1, JS_PROXY_TYPE); 27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 271480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 2715f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2723f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 2724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2726f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the object is not a JSReceiver, we return null. 27281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &null); 2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 2730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE); 27313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Map is now in r0. 2732f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, &null); 27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Return 'Function' for JSFunction and JSBoundFunction objects. 27353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ cmp(r1, Operand(FIRST_FUNCTION_TYPE)); 27363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); 27373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ b(hs, &function); 27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the constructor in the map is a JS function. 2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register instance_type = r2; 2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ GetMapConstructor(r0, r0, r1, instance_type); 2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(instance_type, Operand(JS_FUNCTION_TYPE)); 2743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &non_function_constructor); 2744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r0 now contains the constructor function. Grab the 2746f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 2747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); 2748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset)); 2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 2750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 2752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r0, Heap::kFunction_stringRootIndex); 2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 2757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r0, Heap::kObject_stringRootIndex); 2759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2761f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 2763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kNullValueRootIndex); 2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 27750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 27760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 27777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 27797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 27807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r3; 27817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2782109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(object); 27837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 27857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 27867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 278713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch StringCharCodeAtGenerator generator(object, index, result, &need_conversion, 278813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &need_conversion, &index_out_of_range); 27897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 27907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 27917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 27937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 27947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 27957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 27967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 27977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 27997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the undefined value into the result register, which will 28007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 28017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 28027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 28037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper); 28067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 28080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 28097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 28107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 28117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(CallRuntime* expr) { 28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_LE(2, args->length()); 2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push target, receiver and arguments onto the stack. 2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (Expression* const arg : *args) { 2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(arg); 2818f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS); 2820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Move target to r1. 2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int const argc = args->length() - 2; 2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize)); 2823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the target. 2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r0, Operand(argc)); 2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 2826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(argc + 1); 2827bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Discard the function left on TOS. 2829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->DropAndPlug(1, r0); 2830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) { 2833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(1, args->length()); 2835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(args->at(0)); 2836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(r0); 2837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 2838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r0, FieldMemOperand(r0, Map::kPrototypeOffset)); 2839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(r0); 2840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { 2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference debug_is_active = 2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::debug_is_active_address(isolate()); 2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(debug_is_active)); 2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(r0, MemOperand(ip)); 2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(r0); 2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(r0); 2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { 2854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(2, args->length()); 2856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(0)); 2857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(1)); 2858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label runtime, done; 2860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2861bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &runtime, 2862bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 2863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1); 2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(r3); 2865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(r2); 2866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); 2867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 2869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 2870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset)); 2871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset)); 2872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); 2873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(&done); 2874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&runtime); 2876109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kCreateIterResultObject); 2877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(r0); 2880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { 28843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Push function. 28853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadNativeContextSlot(expr->context_index(), r0); 28863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch PushOperand(r0); 28873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 2888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push undefined as the receiver. 2889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2890109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { 28953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 28973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetCallPosition(expr); 2899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r0, Operand(arg_count)); 2901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), 2902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2903109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 2904bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 2905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 2911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2912589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Property* property = expr->expression()->AsProperty(); 2913589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2915589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (property != NULL) { 2916589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->obj()); 2917589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->key()); 2918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(is_strict(language_mode()) 2919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ? Runtime::kDeleteProperty_Strict 2920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Runtime::kDeleteProperty_Sloppy); 292169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(r0); 2922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 2923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Delete of an unqualified identifier is disallowed in strict mode but 2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // "delete this" is allowed. 2926f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool is_this = var->is_this(); 2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(is_sloppy(language_mode()) || is_this); 2928f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (var->IsUnallocated()) { 2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalObject(r2); 2930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r1, Operand(var->name())); 2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(r2, r1); 2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kDeleteProperty_Sloppy); 2933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 2934589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (var->IsStackAllocated() || var->IsContextSlot()) { 2935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-global, non-dynamic variables is false. 2936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression does not have side effects. 2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(is_this); 2938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Non-global variable. Call the runtime to try to delete from the 2940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // context where the variable was introduced. 2941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(var->name()); 2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kDeleteLookupSlot); 2943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 2944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 29451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-property, non-variable reference is true. 2947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression may have side effects. 2948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 2949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(true); 2950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2952f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 2955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2956e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 29570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Heap::kUndefinedValueRootIndex); 2958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 2962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (context()->IsEffect()) { 2964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Unary NOT has no side effects so it's only necessary to visit the 2965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // subexpression. Match the optimizing compiler by not branching. 2966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context()->IsTest()) { 29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const TestContext* test = TestContext::cast(context()); 29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The labels are swapped for the recursive call. 29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->false_label(), 29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->true_label(), 29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->fall_through()); 29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(test->true_label(), test->false_label()); 2975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 29763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We handle value contexts explicitly rather than simply visiting 29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for control and plugging the control flow into the context, 29783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // because we need to prepare a pair of extra administrative AST ids 29793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for the optimizing compiler. 2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); 29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false, done; 29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_false, 29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true, 29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true); 2986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1); 29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_true); 2988bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->MaterializeTrueId(), 2989bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 29903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kTrueValueRootIndex); 29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsStackValue()) __ push(r0); 29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_false); 2994bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->MaterializeFalseId(), 2995bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kFalseValueRootIndex); 29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsStackValue()) __ push(r0); 29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 2999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 3004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AccumulatorValueContext context(this); 30070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 30080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(r3, r0); 3010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET); 30110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3012d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 30133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 3016d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 30173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3018d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 3019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3020d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 3022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); 3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CountOperation"); 302580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 3027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(prop); 3028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 3030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); 30320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 30333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->expression()->AsVariableProxy()); 30343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 3035e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 30360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 3037c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(ip, Operand(Smi::kZero)); 3038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(ip); 3039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (assign_type) { 3041958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_PROPERTY: { 3042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put the object both on the stack and in the register. 3043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->obj()); 3044958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 3045958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitNamedPropertyLoad(prop); 3046958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 3047958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3049958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_SUPER_PROPERTY: { 3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); 3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue( 3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prop->obj()->AsSuperPropertyReference()->home_object()); 3053109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 3054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r1; 3055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, kPointerSize)); 3056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 3057109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 3058958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitNamedSuperPropertyLoad(prop); 3059958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 3060958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3061958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3062958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: { 3063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); 3064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue( 3065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prop->obj()->AsSuperPropertyReference()->home_object()); 3066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForAccumulatorValue(prop->key()); 3067109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 3068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const Register scratch = r1; 3069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, 2 * kPointerSize)); 3070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 3071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(scratch, MemOperand(sp, 2 * kPointerSize)); 3072109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(scratch); 3073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(result_register()); 3074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitKeyedSuperPropertyLoad(prop); 3075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 3076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_PROPERTY: { 3079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->obj()); 3080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->key()); 3081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(LoadDescriptor::ReceiverRegister(), 3082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MemOperand(sp, 1 * kPointerSize)); 3083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0)); 3084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitKeyedPropertyLoad(prop); 3085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 3086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 3088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case VARIABLE: 3089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 3090e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We need a second deoptimization point after loading the value 3094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // in case evaluating the property load my have a side effect. 30958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (assign_type == VARIABLE) { 3096bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER); 30978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 3098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER); 30998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline smi case if we are in a loop. 3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label stub_call, done; 3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count_value = expr->op() == Token::INC ? 1 : -1; 3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(expr->op())) { 3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfNotSmi(r0, &slow); 3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save result for postfix expressions. 3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the result on the stack. If we have a named or keyed property 3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we store the result under the receiver that is currently on top 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the stack. 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r0); 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_SUPER_PROPERTY: 3124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(r0, MemOperand(sp, 2 * kPointerSize)); 3125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, 2 * kPointerSize)); 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 3130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(r0, MemOperand(sp, 3 * kPointerSize)); 3131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(vc, &done); 3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call stub. Undo operation first. 3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r0, r0, Operand(Smi::FromInt(count_value))); 3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&stub_call); 3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 31433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 31443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Convert old value into a number. 314513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 3146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 3147bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER); 3148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 3150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 31510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 31520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 31530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 31540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 31550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 31560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 3157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r0); 31580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 31590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 31600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(r0, MemOperand(sp, kPointerSize)); 31610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 3162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_SUPER_PROPERTY: 3163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(r0, MemOperand(sp, 2 * kPointerSize)); 3164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 31650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 31660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(r0, MemOperand(sp, 2 * kPointerSize)); 31670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 3168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 3169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ str(r0, MemOperand(sp, 3 * kPointerSize)); 3170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 31710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 3172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3175d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stub_call); 3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, r0); 3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r0, Operand(Smi::FromInt(count_value))); 3179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(expr); 3181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3182109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code(); 3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->CountBinOpFeedbackId()); 31843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 3185d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 3186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in r0. 3188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 3189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case VARIABLE: { 3190c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 3191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 31920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 3193c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), 3194c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 3195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), 3196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 3197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context.Plug(r0); 31980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 31990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For all contexts except EffectConstant We have the result on 3200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 32010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 32020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3205c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), 3206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 3207bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), 3208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 3209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 3210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3212c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 3213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 3214109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 3215f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); 3216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 3217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 32180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 32190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 32220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_SUPER_PROPERTY: { 3227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitNamedSuperPropertyStore(prop); 3228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 3229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (expr->is_postfix()) { 3230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!context()->IsEffect()) { 3231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier context()->PlugTOS(); 3232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 3234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier context()->Plug(r0); 3235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 3237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: { 3239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitKeyedSuperPropertyStore(prop); 3240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 3241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (expr->is_postfix()) { 3242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!context()->IsEffect()) { 3243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier context()->PlugTOS(); 3244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 3246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier context()->Plug(r0); 3247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 3249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 3250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 3251109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperands(StoreDescriptor::ReceiverRegister(), 3252109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StoreDescriptor::NameRegister()); 3253f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->CountSlot()); 3254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 3255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 32560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 32570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 3258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 32600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 32643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 32653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 32663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 32673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 32683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 32693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 32703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> check) { 32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false; 32723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_true = NULL; 32733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_false = NULL; 32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fall_through = NULL; 32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 32763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &if_true, &if_false, &fall_through); 32773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 32780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForTypeofValue(sub_expr); 32800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 32813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(check, factory->number_string())) { 3285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_true); 328680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 328780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 328880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, ip); 328980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->string_string())) { 3291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 3292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); 3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(lt, if_true, if_false, fall_through); 3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->symbol_string())) { 3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(r0, if_false); 3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(r0, r0, r1, SYMBOL_TYPE); 3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 3298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->boolean_string())) { 3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(r0, Heap::kTrueValueRootIndex); 3300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(r0, Heap::kFalseValueRootIndex); 330280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->undefined_string())) { 3304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(r0, Heap::kNullValueRootIndex); 3305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(eq, if_false); 3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 330780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 330880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 330980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 3310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(r1, Operand(1 << Map::kIsUndetectable)); 3311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(ne, if_true, if_false, fall_through); 3312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->function_string())) { 3314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 3315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 3316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 3317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ and_(r1, r1, 3318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); 3319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r1, Operand(1 << Map::kIsCallable)); 33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Split(eq, if_true, if_false, fall_through); 3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->object_string())) { 3322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r0, Heap::kNullValueRootIndex); 3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, if_true); 3325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 3326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(r0, r0, r1, FIRST_JS_RECEIVER_TYPE); 33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(lt, if_false); 3328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check for callable or undetectable objects => false. 3329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 3330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ tst(r1, Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); 3331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(eq, if_true, if_false, fall_through); 3332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// clang-format off 3333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \ 3334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (String::Equals(check, factory->type##_string())) { \ 3335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(r0, if_false); \ 3336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); \ 3337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r0, Heap::k##Type##MapRootIndex); \ 3338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(eq, if_true, if_false, fall_through); 3339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SIMD128_TYPES(SIMD128_TYPE) 3340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef SIMD128_TYPE 3341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // clang-format on 334280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 334380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 3344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(if_true, if_false); 3346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3348f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 3351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 33523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First we try a fast inlined version of the compare when one of 33533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the operands is a literal. 33543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryLiteralCompare(expr)) return; 33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 3357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 3358f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3359f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3360f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 336180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 33620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 33630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 336480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 33653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Token::Value op = expr->op(); 33660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 336780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 3368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 33690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 3370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 3371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch EmitHasProperty(); 33723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 3373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r0, Heap::kTrueValueRootIndex); 337480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 3378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(expr->right()); 3379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 3380109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(r1); 3381c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET); 3382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 3383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(r0, Heap::kTrueValueRootIndex); 338480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 3386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 33890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 3390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = CompareIC::ComputeCondition(op); 3392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(r1); 3393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 33940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 33960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 339780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 339880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ orr(r2, r0, Operand(r1)); 33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block patch_site.EmitJumpIfNotSmi(r2, &slow_case); 340080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, r0); 34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Split(cond, if_true, if_false, NULL); 340280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 340380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); 3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 34073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 34083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand::Zero()); 34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Split(cond, if_true, if_false, fall_through); 34113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 34123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 34133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 3415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 34160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 34183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 34203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 34213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 34223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NilValue nil) { 342380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 342480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 342580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 342680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 34270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 34280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 342980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 34303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(sub_expr); 34313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 34323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->op() == Token::EQ_STRICT) { 3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex nil_value = nil == kNullValue ? 3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kNullValueRootIndex : 3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kUndefinedValueRootIndex; 3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r1, nil_value); 343780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, r1); 343880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 34403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ JumpIfSmi(r0, if_false); 34413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 34423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 34433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ tst(r1, Operand(1 << Map::kIsUndetectable)); 34443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Split(ne, if_true, if_false, fall_through); 344580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 34460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 344780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 344880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 344980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 34500d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 34510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return r0; 34520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 34550d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 34560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return cp; 34570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 34580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 34593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) { 34603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 34613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ ldr(value, MemOperand(fp, frame_offset)); 34623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 34630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3464d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 3466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(value, MemOperand(fp, frame_offset)); 3467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 34683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3470d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(dst, ContextMemOperand(cp, context_index)); 34723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 34733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 3474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 34753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 3476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DeclarationScope* closure_scope = scope()->GetClosureScope(); 3477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (closure_scope->is_script_scope() || 3478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch closure_scope->is_module_scope()) { 3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Contexts nested in the native context have a canonical empty function 34803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // as their closure, not the anonymous closure containing the global 3481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // code. 3482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::CLOSURE_INDEX, ip); 3483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (closure_scope->is_eval_scope()) { 34843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Contexts created by a call to eval have the same closure as the 34853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // context calling eval, not the anonymous closure containing the eval 34863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Fetch it from the context. 3487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(ip, ContextMemOperand(cp, Context::CLOSURE_INDEX)); 34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 3489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(closure_scope->is_function_scope()); 34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 34913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 3492109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(ip); 34933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 34943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 3497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 3498e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3499d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(r1)); 3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store pending message while executing finally block. 3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_obj = 3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(pending_message_obj)); 3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, MemOperand(ip)); 3506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(r1); 3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ClearPendingMessage(); 3509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 3513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(r1)); 3514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore pending message from stack. 3515109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(r1); 3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_obj = 3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 3518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(pending_message_obj)); 3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, MemOperand(ip)); 3520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 3521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 3522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::ClearPendingMessage() { 3524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!result_register().is(r1)); 3525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference pending_message_obj = 3526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 3527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); 3528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ip, Operand(pending_message_obj)); 3529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(r1, MemOperand(ip)); 3530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 353269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 3533109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::DeferredCommands::EmitCommands() { 3534109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!result_register().is(r1)); 3535109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(result_register()); // Restore the accumulator. 3536109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(r1); // Get the token. 3537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch for (DeferredCommand cmd : commands_) { 3538109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label skip; 3539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(r1, Operand(Smi::FromInt(cmd.token))); 3540109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ b(ne, &skip); 3541109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch switch (cmd.command) { 3542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case kReturn: 3543109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen_->EmitUnwindAndReturn(); 3544109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 3545109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case kThrow: 3546109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(result_register()); 3547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kReThrow); 3548109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 3549109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case kContinue: 3550109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen_->EmitContinue(cmd.target); 3551109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 3552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch case kBreak: 3553109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen_->EmitBreak(cmd.target); 3554109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 3555109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&skip); 3557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 3558109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 355969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 356069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __ 356169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Address GetInterruptImmediateLoadAddress(Address pc) { 3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address load_address = pc - 2 * Assembler::kInstrSize; 3565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!FLAG_enable_embedded_constant_pool) { 3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address))); 3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) { 3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is an extended constant pool lookup. 3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::IsSupported(ARMv7)) { 3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load_address -= 2 * Assembler::kInstrSize; 3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovW(Memory::int32_at(load_address))); 3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovT( 3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + Assembler::kInstrSize))); 3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load_address -= 4 * Assembler::kInstrSize; 3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address))); 3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + Assembler::kInstrSize))); 3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + 2 * Assembler::kInstrSize))); 3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + 3 * Assembler::kInstrSize))); 3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (CpuFeatures::IsSupported(ARMv7) && 3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::IsMovT(Memory::int32_at(load_address))) { 3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is a movw / movt immediate load. 3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load_address -= Assembler::kInstrSize; 3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovW(Memory::int32_at(load_address))); 3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (!CpuFeatures::IsSupported(ARMv7) && 3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::IsOrrImmed(Memory::int32_at(load_address))) { 3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is a mov / orr immediate load. 3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load_address -= 3 * Assembler::kInstrSize; 3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address))); 3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + Assembler::kInstrSize))); 3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + 2 * Assembler::kInstrSize))); 3598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is a small constant pool lookup. 3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(load_address))); 3601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return load_address; 3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code, 3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc, 3608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BackEdgeState target_state, 3609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* replacement_code) { 3610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc); 3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address branch_address = pc_immediate_load_address - Assembler::kInstrSize; 3612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate* isolate = unoptimized_code->GetIsolate(); 3613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodePatcher patcher(isolate, branch_address, 1); 3614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (target_state) { 3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INTERRUPT: 3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <decrement profiling counter> 3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bpl ok 3619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; load interrupt stub address into ip - either of (for ARMv7): 3620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; <small cp load> | <extended cp load> | <immediate load> 3621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr ip, [pc/pp, #imm] | movw ip, #imm | movw ip, #imm 3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | movt ip, #imm | movw ip, #imm 3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | ldr ip, [pp, ip] 3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; or (for ARMv6): 3625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; <small cp load> | <extended cp load> | <immediate load> 3626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr ip, [pc/pp, #imm] | mov ip, #imm | mov ip, #imm 3627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 3630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blx ip 3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <reset profiling counter> 3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok-label 3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate branch offset to the ok-label - this is the difference 3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // between the branch address and |pc| (which points at <blx ip>) plus 3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // kProfileCounterResetSequence instructions 3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int branch_offset = pc - Instruction::kPCReadOffset - branch_address + 3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kProfileCounterResetSequenceLength; 3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->b(branch_offset, pl); 3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ON_STACK_REPLACEMENT: 3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <decrement profiling counter> 3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // mov r0, r0 (NOP) 3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; load on-stack replacement address into ip - either of (for ARMv7): 3646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; <small cp load> | <extended cp load> | <immediate load> 3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr ip, [pc/pp, #imm] | movw ip, #imm | movw ip, #imm 3648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | movt ip, #imm> | movw ip, #imm 3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | ldr ip, [pp, ip] 3650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; or (for ARMv6): 3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; <small cp load> | <extended cp load> | <immediate load> 3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr ip, [pc/pp, #imm] | mov ip, #imm | mov ip, #imm 3653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 3654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blx ip 3657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <reset profiling counter> 3658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok-label 3659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->nop(); 3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace the call address. 3664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Assembler::set_target_address_at(isolate, pc_immediate_load_address, 3665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch unoptimized_code, replacement_code->entry()); 3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code, pc_immediate_load_address, replacement_code); 3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 3673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate, 3674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* unoptimized_code, 3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc) { 3676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsBlxIp(Memory::int32_at(pc - Assembler::kInstrSize))); 3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc); 3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address branch_address = pc_immediate_load_address - Assembler::kInstrSize; 36803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#ifdef DEBUG 3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address interrupt_address = Assembler::target_address_at( 3682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pc_immediate_load_address, unoptimized_code); 36833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif 3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Assembler::IsBranch(Assembler::instr_at(branch_address))) { 3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(interrupt_address == 3687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->InterruptCheck()->entry()); 3688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return INTERRUPT; 3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsNop(Assembler::instr_at(branch_address))); 3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(interrupt_address == 36943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch isolate->builtins()->OnStackReplacement()->entry()); 36953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return ON_STACK_REPLACEMENT; 3696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 3701f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3702f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 3703