1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 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_ARM64 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/ast/compile-time-value.h" 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h" 962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins-constructor.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" 1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/full-codegen/full-codegen.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/code-stubs-arm64.h" 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/arm64/frames-arm64.h" 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/macro-assembler-arm64.h" 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define __ ACCESS_MASM(masm()) 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass JumpPatchSite BASE_EMBEDDED { 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm), reg_(NoReg) { 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_emitted_ = false; 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~JumpPatchSite() { 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (patch_site_.is_bound()) { 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info_emitted_); 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg_.IsNone()); 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitJumpIfNotSmi(Register reg, Label* target) { 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This code will be patched by PatchInlinedSmiCode, in ic-arm64.cc. 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionAccurateScope scope(masm_, 1); 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info_emitted_); 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg.Is64Bits()); 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!reg.Is(csp)); 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_ = reg; 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&patch_site_); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tbz(xzr, 0, target); // Always taken before patched. 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitJumpIfSmi(Register reg, Label* target) { 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This code will be patched by PatchInlinedSmiCode, in ic-arm64.cc. 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionAccurateScope scope(masm_, 1); 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info_emitted_); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg.Is64Bits()); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!reg.Is(csp)); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_ = reg; 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&patch_site_); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tbnz(xzr, 0, target); // Never taken before patched. 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitJumpIfEitherNotSmi(Register reg1, Register reg2, Label* target) { 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UseScratchRegisterScope temps(masm_); 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = temps.AcquireX(); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Orr(temp, reg1, reg2); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitJumpIfNotSmi(temp, target); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitPatchInfo() { 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope scope(masm_); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InlineSmiCheckInfo::Emit(masm_, reg_, &patch_site_); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_emitted_ = true; 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 82109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MacroAssembler* masm() { return masm_; } 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm_; 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label patch_site_; 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg_; 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool info_emitted_; 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code for a JS function. On entry to the function the receiver 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and arguments have been pushed on the stack left to right. The actual 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// argument count matches the formal parameter count expected by the 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// function. 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The live registers are: 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - x1: the JS function object being called (i.e. ourselves). 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - x3: the new target value 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - cp: our context. 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - fp: our caller's frame pointer. 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - jssp: stack pointer. 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - lr: return address. 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The function builds a JS frame. See JavaScriptFrameConstants in 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// frames-arm.h for its layout. 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::Generate() { 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompilationInfo* info = info_; 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch profiling_counter_ = isolate()->factory()->NewCell( 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetFunctionPosition(literal()); 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Function compiled by full code generator"); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm_); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) { 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int receiver_offset = info->scope()->num_parameters() * kXRegSize; 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x10, receiver_offset); 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertNotSmi(x10); 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(x10, x10, x11, FIRST_JS_RECEIVER_TYPE); 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Assert(ge, kSloppyFunctionExpectsJSReceiverReceiver); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The MANUAL indicates that the scope shouldn't actually generate code 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to set up the frame because we do it manually below. 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This call emits the following sequence in a way that can be patched for 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code ageing support: 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push(lr, fp, cp, x1); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add(fp, jssp, 2 * kPointerSize); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->set_prologue_offset(masm_->pc_offset()); 134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Prologue(info->GeneratePreagedPrologue()); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Increment invocation count for the function. 137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment cmnt(masm_, "[ Increment invocation count"); 13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Ldr(x11, FieldMemOperand(x1, JSFunction::kFeedbackVectorOffset)); 14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Ldr(x11, FieldMemOperand(x11, Cell::kValueOffset)); 14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Ldr(x10, FieldMemOperand( 14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch x11, FeedbackVector::kInvocationCountIndex * kPointerSize + 14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackVector::kHeaderSize)); 144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Add(x10, x10, Operand(Smi::FromInt(1))); 14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Str(x10, FieldMemOperand( 14662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch x11, FeedbackVector::kInvocationCountIndex * kPointerSize + 14762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackVector::kHeaderSize)); 148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reserve space on the stack for locals. 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { Comment cmnt(masm_, "[ Allocate locals"); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int locals_count = info->scope()->num_stack_slots(); 153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(locals_count); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count > 0) { 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= 128) { 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(jssp.Is(__ StackPointer())); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Sub(x10, jssp, locals_count * kPointerSize); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x10, Heap::kRealStackLimitRootIndex); 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(hs, &ok); 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&ok); 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_optimize_for_size) { 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushMultipleTimes(x10 , locals_count); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kMaxPushes = 32; 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= kMaxPushes) { 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int loop_iterations = locals_count / kMaxPushes; 171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(x2, loop_iterations); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop_header; 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&loop_header); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do pushes. 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushMultipleTimes(x10 , kMaxPushes); 176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Subs(x2, x2, 1); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, &loop_header); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int remaining = locals_count % kMaxPushes; 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the remaining pushes. 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushMultipleTimes(x10 , remaining); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool function_in_register_x1 = true; 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 188f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (info->scope()->NeedsContext()) { 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument to NewContext is the function, which is still in x1. 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Allocate context"); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool need_write_barrier = true; 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->is_script_scope()) { 194f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Mov(x10, Operand(info->scope()->scope_info())); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x1, x10); 196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNewScriptContext); 197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::ScriptContext(), 198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The new target value is not used, clobbering is safe. 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_NULL(info->scope()->new_target_var()); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->new_target_var() != nullptr) { 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(x3); // Preserve new target. 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (slots <= 20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) { 20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = CodeFactory::FastNewFunctionContext( 20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), info->scope()->scope_type()); 209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Mov(FastNewFunctionContextDescriptor::SlotsRegister(), slots); 21062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(callable.code(), RelocInfo::CODE_TARGET); 21162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Result of the FastNewFunctionContext builtin is always in new space. 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch need_write_barrier = false; 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(x1); 21562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(Smi::FromInt(info->scope()->scope_type())); 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext); 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->new_target_var() != nullptr) { 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(x3); // Restore new target. 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_in_register_x1 = false; 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Context is returned in x0. It replaces the context passed to us. 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's saved in the stack and kept live in cp. 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(cp, x0); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset)); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy any necessary parameters into the context. 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_parameters = info->scope()->num_parameters(); 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int first_parameter = info->scope()->has_this_declaration() ? -1 : 0; 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = first_parameter; i < num_parameters; i++) { 231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* var = 232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parameter_offset = StandardFrameConstants::kCallerSPOffset + 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (num_parameters - 1 - i) * kPointerSize; 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load parameter from stack. 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, MemOperand(fp, parameter_offset)); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store it in the context. 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand target = ContextMemOperand(cp, var->index()); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x10, target); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier. 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_write_barrier) { 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ RecordWriteContextSlot(cp, static_cast<int>(target.offset()), x10, 245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch x11, kLRHasBeenSaved, kDontSaveFPRegs); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInNewSpace(cp, &done); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kExpectedNewSpaceObject); 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Register holding this function and new target are both trashed in case we 257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // bailout here. But since that can happen only when new target is not used 258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // and we allocate a context, the value of |function_in_register| is correct. 259bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::FunctionContext(), 260bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 26262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We don't support new.target and rest parameters here. 26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NULL(info->scope()->new_target_var()); 26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NULL(info->scope()->rest_parameter()); 26562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NULL(info->scope()->this_function_var()); 266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* arguments = info->scope()->arguments(); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (arguments != NULL) { 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Function uses arguments object. 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Allocate arguments object"); 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!function_in_register_x1) { 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load this again, if it's used by the local context below. 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ldr(x1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 275109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (is_strict(language_mode()) || !has_simple_parameters()) { 27662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = CodeFactory::FastNewStrictArguments(isolate()); 27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(callable.code(), RelocInfo::CODE_TARGET); 27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RestoreContext(); 279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (literal()->has_duplicate_parameters()) { 280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(x1); 281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kNewSloppyArguments_Generic); 282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 28362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = CodeFactory::FastNewSloppyArguments(isolate()); 28462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(callable.code(), RelocInfo::CODE_TARGET); 28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RestoreContext(); 286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetVar(arguments, x0, x1, x2); 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace) { 292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kTraceEnter); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Visit the declarations and body. 296bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::FunctionEntry(), 297bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 2983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Declarations"); 3003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch VisitDeclarations(scope()->declarations()); 3013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Assert that the declarations do not use ICs. Otherwise the debugger 3043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // won't be able to redirect a PC at an IC to the correct IC in newly 3053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // recompiled code. 3063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(0, ic_total_count_); 307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Comment cmnt(masm_, "[ Stack check"); 310bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::Declarations(), 311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 3123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label ok; 3133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(jssp.Is(__ StackPointer())); 3143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CompareRoot(jssp, Heap::kStackLimitRootIndex); 3153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ B(hs, &ok); 3163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch PredictableCodeSizeScope predictable(masm_, 3173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Assembler::kCallSizeWithRelocation); 3183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); 3193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Bind(&ok); 3203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Comment cmnt(masm_, "[ Body"); 3243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(loop_depth() == 0); 3253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch VisitStatements(literal()->body()); 3263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(loop_depth() == 0); 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Always emit a 'return undefined' in case control fell off the end of 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the body. 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { Comment cmnt(masm_, "[ return <undefined>;"); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Force emission of the pools, so they don't get emitted in the middle 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the back edge table. 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->CheckVeneerPool(true, false); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->CheckConstPool(true, false); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 342c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid FullCodeGenerator::ClearAccumulator() { __ Mov(x0, Smi::kZero); } 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(profiling_counter_)); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset)); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Subs(x3, x3, Smi::FromInt(delta)); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset)); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() { 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int reset_value = FLAG_interrupt_budget; 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(profiling_counter_)); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, Smi::FromInt(reset_value)); 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset)); 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* back_edge_target) { 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(jssp.Is(__ StackPointer())); 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Back edge bookkeeping"); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block literal pools whilst emitting back edge code. 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope block_const_pool(masm_); 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(back_edge_target->is_bound()); 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We want to do a round rather than a floor of distance/kCodeSizeMultiplier 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to reduce the absolute error due to the integer division. To do that, 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we add kCodeSizeMultiplier/2 to the distance (equivalent to adding 0.5 to 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the result). 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int>(masm_->SizeOfCodeGeneratedSince(back_edge_target) + 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch kCodeSizeMultiplier / 2); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int weight = Min(kMaxBackEdgeWeight, 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Max(1, distance / kCodeSizeMultiplier)); 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterDecrement(weight); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(pl, &ok); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record a mapping of this PC offset to the OSR id. This is used to find 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the AST id from the unoptimized code in order to use it as a key into 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the deoptimization input data found in the optimized code. 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordBackEdge(stmt->OsrEntryId()); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterReset(); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&ok); 390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS); 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record a mapping of the OSR id to this PC. This is used if the OSR 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // entry becomes the target of a bailout. We don't expect it to be, but 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we want it to work if it is. 394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence( 398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bool is_tail_call) { 399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Pretend that the exit is a backwards jump to the entry. 400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int weight = 1; 401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (info_->ShouldSelfOptimize()) { 402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch weight = FLAG_interrupt_budget / FLAG_self_opt_count; 403109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int distance = masm_->pc_offset() + kCodeSizeMultiplier / 2; 405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier)); 406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 407109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterDecrement(weight); 408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label ok; 409109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ B(pl, &ok); 410109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Don't need to save result register if we are going to do a tail call. 411109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!is_tail_call) { 412109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(x0); 413109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 414109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 415109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!is_tail_call) { 416109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(x0); 417109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 418109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterReset(); 419109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Bind(&ok); 420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Return sequence"); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (return_label_.is_bound()) { 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&return_label_); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&return_label_); 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace) { 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the return value on the stack as the parameter. 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Runtime::TraceExit returns its parameter in x0. 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kTraceExit); 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(x0.Is(result_register())); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterHandlingForReturnSequence(false); 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetReturnPosition(literal()); 440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const Register& current_sp = __ StackPointer(); 441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Nothing ensures 16 bytes alignment here. 442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!current_sp.Is(csp)); 443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(current_sp, fp); 444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ldp(fp, lr, MemOperand(current_sp, 2 * kXRegSize, PostIndex)); 445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Drop the arguments and receiver and return. 446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(all): This implementation is overkill as it supports 2**31+1 447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments, consider how to improve it without creating a security 448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // hole. 449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2); 450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Add(current_sp, current_sp, ip0); 451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(); 452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t arg_count = info_->scope()->num_parameters() + 1; 453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ dc64(kXRegSize * arg_count); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid FullCodeGenerator::RestoreContext() { 458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->GetVar(result_register(), var); 464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(result_register()); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Root values have no side effects. 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug( 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex index) const { 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), index); 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug( 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex index) const { 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), index); 482109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(result_register()); 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch false_label_); 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index == Heap::kUndefinedValueRootIndex || 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index == Heap::kNullValueRootIndex || 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index == Heap::kFalseValueRootIndex) { 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) __ B(false_label_); 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (index == Heap::kTrueValueRootIndex) { 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) __ B(true_label_); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), index); 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoTest(this); 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug( 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> lit) const { 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result_register(), Operand(lit)); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Immediates cannot be pushed directly. 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result_register(), Operand(lit)); 515109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(result_register()); 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true, 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true_label_, 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch false_label_); 52462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(lit->IsNullOrUndefined(isolate()) || !lit->IsUndetectable()); 52562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (lit->IsNullOrUndefined(isolate()) || lit->IsFalse(isolate())) { 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) __ B(false_label_); 52713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) { 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) __ B(true_label_); 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (lit->IsString()) { 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::cast(*lit)->length() == 0) { 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) __ B(false_label_); 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) __ B(true_label_); 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (lit->IsSmi()) { 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Smi::cast(*lit)->value() == 0) { 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) __ B(false_label_); 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) __ B(true_label_); 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For simplicity we always test the accumulator register. 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result_register(), Operand(lit)); 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoTest(this); 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg) const { 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (count > 1) codegen()->DropOperands(count - 1); 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(reg, 0); 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_false) const { 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == materialize_false); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_true); 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug( 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_true, 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_false) const { 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_true); 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_false); 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug( 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_true, 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_false) const { 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_true); 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kTrueValueRootIndex); 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_false); 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kFalseValueRootIndex); 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(x10); 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_false) const { 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == true_label_); 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_false == false_label_); 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex value_root_index = 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), value_root_index); 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex value_root_index = 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, value_root_index); 609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(x10); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true, 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true_label_, 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch false_label_); 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (flag) { 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) { 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(true_label_); 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) { 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(false_label_); 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DoTest(Expression* condition, 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true, 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false, 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through) { 6343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate()); 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, condition->test_id()); 636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(eq, if_true, if_false, fall_through); 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If (cond), branch to if_true. 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If (!cond), branch to if_false. 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// fall_through is used as an optimization in cases where only one branch 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// instruction is necessary. 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::Split(Condition cond, 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true, 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false, 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through) { 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (if_false == fall_through) { 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(cond, if_true); 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (if_true == fall_through) { 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(if_false != fall_through); 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(NegateCondition(cond), if_false); 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(cond, if_true); 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(if_false); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) { 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Offset is negative because higher indexes are at lower addresses. 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = -var->index() * kXRegSize; 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust by a (parameter or local) base offset. 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsParameter()) { 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset += (info_->scope()->num_parameters() + 1) * kPointerSize; 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset += JavaScriptFrameConstants::kLocal0Offset; 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MemOperand(fp, offset); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int context_chain_length = scope()->ContextChainLength(var->scope()); 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadContext(scratch, context_chain_length); 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ContextMemOperand(scratch, var->index()); 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return StackOperand(var); 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) { 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use destination as scratch. 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, dest); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(dest, location); 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::SetVar(Variable* var, 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register src, 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch0, 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1) { 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(src, scratch0, scratch1)); 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, scratch0); 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(src, location); 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the write barrier code if the location is in the heap. 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch0 contains the correct context. 705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ RecordWriteContextSlot(scratch0, static_cast<int>(location.offset()), 706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch src, scratch1, kLRHasBeenSaved, kDontSaveFPRegs); 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool should_normalize, 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true, 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false) { 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only prepare for bailouts before splits if we're in a test 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context. Otherwise, we let the Visit function deal with the 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // preparation to avoid preparing with the same AST id twice. 718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!context()->IsTest()) return; 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): Investigate to see if there is something to work on here. 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (should_normalize) { 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&skip); 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 725bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr, BailoutState::TOS_REGISTER); 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (should_normalize) { 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, Heap::kTrueValueRootIndex); 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, NULL); 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&skip); 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The variable in the declaration always resides in the current function 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context. 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); 738109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we're not inside a with or catch context. 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x1, FieldMemOperand(cp, HeapObject::kMapOffset)); 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x1, Heap::kWithContextMapRootIndex); 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(ne, kDeclarationInWithContext); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x1, Heap::kCatchContextMapRootIndex); 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(ne, kDeclarationInCatchContext); 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration( 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* declaration) { 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::UNALLOCATED: { 755bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!variable->binding_needs_init()); 75662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch globals_->Add(variable->name(), zone()); 75762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot = proxy->VariableFeedbackSlot(); 758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!slot.IsInvalid()); 759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 760bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch globals_->Add(isolate()->factory()->undefined_value(), zone()); 76162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch globals_->Add(isolate()->factory()->undefined_value(), zone()); 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: 766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (variable->binding_needs_init()) { 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x10, StackOperand(variable)); 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: 774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (variable->binding_needs_init()) { 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x10, ContextMemOperand(cp, variable->index())); 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // No write barrier since the_hole_value is in old space. 780bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 78462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case VariableLocation::LOOKUP: 785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration( 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionDeclaration* declaration) { 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::UNALLOCATED: { 79762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch globals_->Add(variable->name(), zone()); 79862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot = proxy->VariableFeedbackSlot(); 79962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!slot.IsInvalid()); 80062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 80162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 80262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We need the slot where the literals array lives, too. 80362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch slot = declaration->fun()->LiteralFeedbackSlot(); 804f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!slot.IsInvalid()); 805f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 80662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> function = 808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_); 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for stack overflow exception. 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (function.is_null()) return SetStackOverflow(); 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(function, zone()); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: { 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Function Declaration"); 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(result_register(), StackOperand(variable)); 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: { 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Function Declaration"); 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(result_register(), ContextMemOperand(cp, variable->index())); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(variable->index()); 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a function, which is not a smi. 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(cp, 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset, 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_register(), 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x2, 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 838bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 84262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case VariableLocation::LOOKUP: 843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime to declare the globals. 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x11, Operand(pairs)); 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register flags = xzr; 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Smi::FromInt(DeclareGlobalsFlags())) { 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = x10; 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags())); 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 85762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ EmitLoadFeedbackVector(x12); 858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(x11, flags, x12); 859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kDeclareGlobals); 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return value is ignored. 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement"); 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ SwitchStatement"); 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Breakable nested_statement(this, stmt); 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetStatementPosition(stmt); 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep the switch value on the stack until a case matches. 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(stmt->tag()); 872bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS); 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<CaseClause*>* clauses = stmt->cases(); 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CaseClause* default_clause = NULL; // Can occur anywhere in the list. 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label next_test; // Recycled for each test. 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile all the tests with branches to their bodies. 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < clauses->length(); i++) { 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CaseClause* clause = clauses->at(i); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch clause->body_target()->Unuse(); 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The default is not a test, but remember it as final fall through. 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (clause->is_default()) { 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default_clause = clause; 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Case comparison"); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&next_test); 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_test.Unuse(); 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the label expression. 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(clause->label()); 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform the comparison as if via '==='. 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, 0); // Switch value. 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(Token::EQ_STRICT)) { 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow_case; 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x1, x0); 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, &next_test); 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // Switch value is no longer needed. 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(clause->body_target()); 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow_case); 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record position before stub call for type feedback. 911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(clause); 912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> ic = 913109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code(); 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, clause->CompareId()); 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&skip); 919bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(clause, BailoutState::TOS_REGISTER); 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test); 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(clause->body_target()); 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&skip); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(x0, &next_test); 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // Switch value is no longer needed. 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(clause->body_target()); 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Discard the test value and jump to the default if present, otherwise to 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the end of the statement. 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&next_test); 933109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(1); // Switch value is no longer needed. 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (default_clause == NULL) { 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(nested_statement.break_label()); 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(default_clause->body_target()); 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile all the case bodies. 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < clauses->length(); i++) { 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Case body"); 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CaseClause* clause = clauses->at(i); 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(clause->body_target()); 945bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS); 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitStatements(clause->statements()); 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(nested_statement.break_label()); 950bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS); 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::VisitForInStatement"); 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ForInStatement"); 957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetStatementPosition(stmt, SKIP_BREAK); 958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 95962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot = stmt->ForInFeedbackSlot(); 960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): This visitor probably needs better comments and a revisit. 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 963109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Get the object to enumerate over. 964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionAsStatementPosition(stmt->enumerable()); 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(stmt->enumerable()); 9663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch OperandStackDepthIncrement(5); 9673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 9683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label loop, exit; 9693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Iteration loop_statement(this, stmt); 9703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch increment_loop_depth(); 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If the object is null or undefined, skip over the loop, otherwise convert 973109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // it to a JS receiver. See ECMA-262 version 5, section 12.6.4. 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label convert, done_convert; 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, &convert); 976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE, &done_convert, ge); 977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfRoot(x0, Heap::kNullValueRootIndex, &exit); 978109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, &exit); 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&convert); 980c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET); 981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done_convert); 983bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER); 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 986bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check cache validity in generated code. If we cannot guarantee cache 987bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // validity, call the runtime system to check cache validity or get the 988bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // property names in a fixed array. Note: Proxies never have an enum cache, 989bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // so will always take the slow path. 990109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label call_runtime; 991109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CheckEnumCache(x0, x15, x10, x11, x12, x13, &call_runtime); 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The enum cache is valid. Load the map of the object being 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // iterated over and use the cache for the iteration. 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label use_cache; 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&use_cache); 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the set of properties to enumerate. 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&call_runtime); 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // Duplicate the enumerable object on the stack. 1002109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kForInEnumerate); 1003bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER); 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we got a map from the runtime call, we can do a fast 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // modification check. Otherwise, we got a fixed array, and we have 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to do a slow check. 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fixed_array, no_descriptors; 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, FieldMemOperand(x0, HeapObject::kMapOffset)); 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x2, Heap::kMetaMapRootIndex, &fixed_array); 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We got a map in register x0. Get the enumeration cache from it. 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&use_cache); 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnumLengthUntagged(x1, x0); 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbz(x1, &no_descriptors); 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadInstanceDescriptors(x0, x2); 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, FieldMemOperand(x2, DescriptorArray::kEnumCacheOffset)); 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(x2, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set up the four remaining stack slots. 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(x1); 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Map, enumeration cache, enum cache length, zero (both last as smis). 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, x2, x1, xzr); 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&loop); 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&no_descriptors); 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&exit); 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We got a fixed array in register x0. Iterate through that. 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&fixed_array); 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(x1, Smi::FromInt(1)); // Smi(1) indicates slow check. 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, FieldMemOperand(x0, FixedArray::kLengthOffset)); 1038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(x1, x0, x2); // Smi and array, fixed array length (as smi). 1039bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS); 1040109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(xzr); // Initial index. 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for doing the condition check. 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&loop); 1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionAsStatementPosition(stmt->each()); 1045958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the current count to x0, load the length to x1. 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PeekPair(x0, x1, 0); 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x0, x1); // Compare to the array length. 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(hs, loop_statement.break_label()); 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Get the current entry of the array into register x0. 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x10, 2 * kXRegSize); 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x10, x10, Operand::UntagSmiAndScale(x0, kPointerSizeLog2)); 1054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ldr(x0, MemOperand(x10, FixedArray::kHeaderSize - kHeapObjectTag)); 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the expected map from the stack or a smi in the 1057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // permanent slow case into register x2. 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x2, 3 * kXRegSize); 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the expected map still matches that of the enumerable. 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If not, we may have to filter the key. 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label update_each; 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, 4 * kXRegSize); 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x11, FieldMemOperand(x1, HeapObject::kMapOffset)); 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x11, x2); 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, &update_each); 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 10683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // We need to filter the key, record slow-path here. 10693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int const vector_index = SmiFromSlot(slot)->value(); 107062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ EmitLoadFeedbackVector(x3); 107162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Mov(x10, Operand(FeedbackVector::MegamorphicSentinel(isolate()))); 1072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Str(x10, FieldMemOperand(x3, FixedArray::OffsetOfElementAt(vector_index))); 1073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1074f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // x0 contains the key. The receiver in x1 is the second argument to the 1075c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // ForInFilter. ForInFilter returns undefined if the receiver doesn't 1076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // have the key or returns the name-converted key. 1077c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET); 1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 1079bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER); 1080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); 1081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ B(eq, loop_statement.continue_label()); 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the 'each' property or variable from the possibly filtered 1084f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // entry in register x0. 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&update_each); 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform the assignment as if via '='. 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { EffectContext context(this); 1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitAssignment(stmt->each(), stmt->EachFeedbackSlot()); 1089bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS); 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body(). 1093bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS); 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for the body of the loop. 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Visit(stmt->body()); 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for going to the next element by incrementing 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the index (smi) stored on top of the stack. 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(loop_statement.continue_label()); 1100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS); 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): We could use a callee saved register to avoid popping. 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x0); 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x0, x0, Smi::FromInt(1)); 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, &loop); 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&loop); 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove the pointers stored on the stack. 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(loop_statement.break_label()); 1111109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(5); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exit and decrement the loop depth. 1114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS); 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&exit); 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch decrement_loop_depth(); 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, 112062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot) { 1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NeedsHomeObject(initializer)); 1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Peek(StoreDescriptor::ReceiverRegister(), 0); 1123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize); 1124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, isolate()->factory()->home_object_symbol()); 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, 1128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset, 112962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot) { 1130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NeedsHomeObject(initializer)); 1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(StoreDescriptor::ReceiverRegister(), x0); 1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize); 1133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, isolate()->factory()->home_object_symbol()); 1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, 1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeofMode typeof_mode) { 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record position before possible IC call. 1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(proxy); 1140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = proxy->var(); 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 114362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Two cases: global variables and all other types of variables. 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (var->location()) { 1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::UNALLOCATED: { 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "Global variable"); 1147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitGlobalVariableLoad(proxy, typeof_mode); 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 1153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: 1154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: { 1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, var->IsContextSlot() 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? "Context variable" 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : "Stack variable"); 1159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { 1160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Throw a reference error when using an uninitialized let/const 1161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // binding in harmony mode. 1162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 1163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GetVar(x0, var); 1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); 1165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Mov(x0, Operand(var->name())); 1166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(x0); 1167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 1168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Bind(&done); 1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(x0); 1170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(var); 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 117662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case VariableLocation::LOOKUP: 1177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 1178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { 1184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Expression* expression = (property == NULL) ? NULL : property->value(); 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expression == NULL) { 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kNullValueRootIndex); 1187109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x10); 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expression); 1190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (NeedsHomeObject(expression)) { 1191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(property->kind() == ObjectLiteral::Property::GETTER || 1192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch property->kind() == ObjectLiteral::Property::SETTER); 1193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3; 1194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObject(expression, offset, property->GetSlot()); 1195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ObjectLiteral"); 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 120362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<BoilerplateDescription> constant_properties = 120462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch expr->GetOrBuildConstantProperties(isolate()); 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 120662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Mov(x2, SmiFromSlot(expr->literal_slot())); 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Operand(constant_properties)); 1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int flags = expr->ComputeFlags(); 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(flags)); 1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (MustCreateObjectLiteralWithRuntime(expr)) { 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x3, x2, x1, x0); 1212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCreateObjectLiteral); 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 121462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = CodeFactory::FastCloneShallowObject( 121562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), expr->properties_count()); 121662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(callable.code(), RelocInfo::CODE_TARGET); 1217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER); 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If result_saved is true the result is on top of the stack. If 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result_saved is false the result is in x0. 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool result_saved = false; 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorTable accessor_table(zone()); 122662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (int i = 0; i < expr->properties()->length(); i++) { 122762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ObjectLiteral::Property* property = expr->properties()->at(i); 122862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!property->is_computed_name()); 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->IsCompileTimeValue()) continue; 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Literal* key = property->key()->AsLiteral(); 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* value = property->value(); 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!result_saved) { 1234109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); // Save result on stack 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_saved = true; 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (property->kind()) { 123862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case ObjectLiteral::Property::SPREAD: 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::CONSTANT: 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fall through. 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::COMPUTED: 1245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // It is safe to use [[Put]] here because the boilerplate already 1246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // contains computed properties with an uninitialized value. 1247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (key->IsStringLiteral()) { 1248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(key->IsPropertyName()); 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->emit_store()) { 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(value); 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(x0)); 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(StoreDescriptor::ReceiverRegister(), 0); 125362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallStoreIC(property->GetSlot(0), key->value(), true); 1254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); 1255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (NeedsHomeObject(value)) { 1257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1)); 1258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(value); 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Peek(x0, 0); 1265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); 1266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(key); 1267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(value); 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->emit_store()) { 1269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (NeedsHomeObject(value)) { 1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObject(value, 2, property->GetSlot()); 1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(x0, Smi::FromInt(SLOPPY)); // Language mode 1273109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); 1274109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kSetProperty); 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(3); 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::PROTOTYPE: 1280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(property->emit_store()); 1281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Duplicate receiver on stack. 1282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Peek(x0, 0); 1283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); 1284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(value); 1285109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kInternalSetPrototype); 128662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch PrepareForBailoutForId(expr->GetIdForPropertySet(i), 1287bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::GETTER: 1290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->emit_store()) { 129113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AccessorTable::Iterator it = accessor_table.lookup(key); 129262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch it->second->bailout_id = expr->GetIdForPropertySet(i); 129313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch it->second->getter = property; 1294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::SETTER: 1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->emit_store()) { 129813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AccessorTable::Iterator it = accessor_table.lookup(key); 129962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch it->second->bailout_id = expr->GetIdForPropertySet(i); 130013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch it->second->setter = property; 1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit code to define accessors, using only a single call to the runtime for 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // each pair of corresponding getters and setters. 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (AccessorTable::Iterator it = accessor_table.begin(); 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch it != accessor_table.end(); 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++it) { 131113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Peek(x10, 0); // Duplicate receiver. 131213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PushOperand(x10); 131313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch VisitForStackValue(it->first); 131413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch EmitAccessor(it->second->getter); 131513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch EmitAccessor(it->second->setter); 131613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Mov(x10, Smi::FromInt(NONE)); 131713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PushOperand(x10); 131813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked); 131913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS); 1320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result_saved) { 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ArrayLiteral"); 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 133362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<ConstantElementsPair> constant_elements = 133462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch expr->GetOrBuildConstantElements(isolate()); 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 133762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Mov(x2, SmiFromSlot(expr->literal_slot())); 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Operand(constant_elements)); 1339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (MustCreateArrayLiteralWithRuntime(expr)) { 1340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(x0, Smi::FromInt(expr->ComputeFlags())); 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x3, x2, x1, x0); 1342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCreateArrayLiteral); 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 134462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = 134562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeFactory::FastCloneShallowArray(isolate(), TRACK_ALLOCATION_SITE); 134662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(callable.code(), RelocInfo::CODE_TARGET); 1347f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch RestoreContext(); 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER); 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool result_saved = false; // Is the result saved to the stack? 1352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* subexprs = expr->values(); 1353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int length = subexprs->length(); 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit code to evaluate all the non-constant subexpressions and to store 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // them into the newly cloned array. 1357f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch for (int array_index = 0; array_index < length; array_index++) { 1358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Expression* subexpr = subexprs->at(array_index); 1359109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!subexpr->IsSpread()); 1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the subexpression is a literal or a simple materialized literal it 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is already set in the cloned array. 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!result_saved) { 1366109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_saved = true; 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(subexpr); 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(StoreDescriptor::NameRegister(), Smi::FromInt(array_index)); 1372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Peek(StoreDescriptor::ReceiverRegister(), 0); 1373f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->LiteralFeedbackSlot()); 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->GetIdForElement(array_index), 1376bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result_saved) { 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Assignment"); 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* property = expr->target()->AsProperty(); 1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(property); 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Evaluate LHS expression. 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Nothing to do here. 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_compound()) { 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need the receiver both on the stack and in the register. 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 0); 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_compound()) { 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize); 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::NameRegister(), 0); 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 142062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 142162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 142262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 142362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For compound assignments we need another deoptimization point after the 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // variable/property load. 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_compound()) { 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { AccumulatorValueContext context(this); 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(expr->target()->AsVariableProxy()); 1433bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER); 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(property); 1437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(property->LoadId(), 1438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(property); 1442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(property->LoadId(), 1443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 144562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 144662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 144762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op = expr->binary_op(); 1453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); // Left operand goes on the stack. 1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->value()); 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccumulatorValueContext context(this); 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(op)) { 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitInlineSmiBinaryOp(expr->binary_operation(), 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch op, 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->target(), 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->value()); 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitBinaryOp(expr->binary_operation(), op); 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deoptimization point in case the binary operation may have side effects. 1467bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER); 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->value()); 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(expr); 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the value. 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 1476c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case VARIABLE: { 1477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->target()->AsVariableProxy(); 1478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), 1479c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 1480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1483c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyAssignment(expr); 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyAssignment(expr); 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 149062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 149162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 149262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 149362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op, 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* left_expr, 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* right_expr) { 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, both_smis, stub_call; 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the arguments. 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left = x1; 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register right = x0; 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x0; 1508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(left); 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform combined smi check on both operands. 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Orr(x10, left, right); 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfSmi(x10, &both_smis); 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&stub_call); 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1517109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope scope(masm_); 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&both_smis); 1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi case. This code works in the same way as the smi-smi case in the type 1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // recording binary operation stub, see 1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // BinaryOpStub::GenerateSmiSmiOperation for comments. 1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): That doesn't exist any more. Where are the comments? 1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The set of operations that needs to be supported here is controlled by 1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FullCodeGenerator::ShouldInlineSmiCase(). 1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SAR: 1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ubfx(right, right, kSmiShift, 5); 1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Asr(result, left, right); 1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bic(result, result, kSmiShiftMask); 1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SHL: 1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ubfx(right, right, kSmiShift, 5); 1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Lsl(result, left, right); 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SHR: 1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If `left >>> right` >= 0x80000000, the result is not representable in a 1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // signed 32-bit smi. 1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ubfx(right, right, kSmiShift, 5); 1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Lsr(x10, left, right); 1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tbnz(x10, kXSignBit, &stub_call); 1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bic(result, x10, kSmiShiftMask); 1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::ADD: 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Adds(x10, left, right); 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(vs, &stub_call); 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result, x10); 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SUB: 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Subs(x10, left, right); 1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(vs, &stub_call); 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result, x10); 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::MUL: { 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_minus_zero, done; 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(static_cast<unsigned>(kSmiShift) == (kXRegSizeInBits / 2)); 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Smulh(x10, left, right); 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(x10, ¬_minus_zero); 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Eor(x11, left, right); 1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tbnz(x11, kXSignBit, &stub_call); 1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result, x10); 1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(¬_minus_zero); 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cls(x11, x10); 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x11, kXRegSizeInBits - kSmiShift); 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, &stub_call); 1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(result, x10); 1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_OR: 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Orr(result, left, right); 1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_AND: 1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(result, left, right); 1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_XOR: 1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Eor(result, left, right); 1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { 1598109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(x1); 1599109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); // Unbound, signals no inlined smi code. 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope scope(masm_); 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 160962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr, FeedbackSlot slot) { 1610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->IsValidReferenceExpressionOrThis()); 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = expr->AsProperty(); 1613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(prop); 1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: { 1617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->AsVariableProxy(); 1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EffectContext context(this); 1619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, 1620c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: { 1624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); // Preserve value. 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(prop->obj()); 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this copy. 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::ReceiverRegister(), x0); 1629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ValueRegister()); // Restore value. 1630f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, prop->key()->AsLiteral()->value()); 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: { 1634109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); // Preserve value. 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->obj()); 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(prop->key()); 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::NameRegister(), x0); 1638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperands(StoreDescriptor::ReceiverRegister(), 1639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StoreDescriptor::ValueRegister()); 1640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(slot); 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 164362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 164462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 164562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 164662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var, MemOperand location) { 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(result_register(), location); 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // RecordWrite may destroy all its register arguments. 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, result_register()); 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(var->index()); 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x1, offset, x10, x11, kLRHasBeenSaved, kDontSaveFPRegs); 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, 166562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot, 1666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch HoleCheckMode hole_check_mode) { 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsUnallocated()) { 1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Global var, const, or let. 1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); 1671f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, var->name()); 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { 1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!var->IsLookupSlot()); 1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand location = VarOperand(var, x1); 1677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform an initialization check for lexically declared variables. 1678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var->binding_needs_init()) { 1679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label assign; 1680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ldr(x10, location); 1681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); 1682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Mov(x10, Operand(var->name())); 1683f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(x10); 1684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 1685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Bind(&assign); 1686f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (var->mode() != CONST) { 1688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 1689f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if (var->throw_on_const_assignment(language_mode())) { 1690f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ CallRuntime(Runtime::kThrowConstAssignError); 1691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { 1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Initializing assignment to const {this} needs a write barrier. 1694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 1695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label uninitialized_this; 1696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand location = VarOperand(var, x1); 1697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ldr(x10, location); 1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfRoot(x10, Heap::kTheHoleValueRootIndex, &uninitialized_this); 1699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(x0, Operand(var->name())); 1700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(x0); 1701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 1702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&uninitialized_this); 1703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 1704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1705f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 1706f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(var->mode() != CONST || op == Token::INIT); 170762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 170862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!var->IsLookupSlot()); 170962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Assignment to var or initializing assignment to let/const in harmony 171062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // mode. 171162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MemOperand location = VarOperand(var, x1); 171262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { 171362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Ldr(x10, location); 171462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ CompareRoot(x10, Heap::kTheHoleValueRootIndex); 171562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Check(eq, kLetBindingReInitialization); 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 171762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 1718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASM_LOCATION("FullCodeGenerator::EmitNamedPropertyAssignment"); 1724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Assignment to a property, using a named store IC. 1725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Property* prop = expr->target()->AsProperty(); 1726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(prop != NULL); 1727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(prop->key()->IsLiteral()); 1728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1729109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 1730f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value()); 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to a property, using a keyed store IC. 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): Could we pass this in registers rather than on the stack? 1742109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperands(StoreDescriptor::NameRegister(), 1743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch StoreDescriptor::ReceiverRegister()); 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(x0)); 1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->AssignmentSlot()); 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1748bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 1749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(x0); 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { 1754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASM_LOCATION("FullCodeGenerator::EmitCallWithLoadIC"); 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the target function. 1758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ConvertReceiverMode convert_mode; 1759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (callee->IsVariableProxy()) { 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { StackValueContext context(this); 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(callee->AsVariableProxy()); 1762bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(callee, BailoutState::NO_REGISTERS); 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push undefined as receiver. This is patched in the method prologue if it 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a sloppy mode method. 1766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch UseScratchRegisterScope temps(masm_); 1768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register temp = temps.AcquireX(); 1769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(temp, Heap::kUndefinedValueRootIndex); 1770109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(temp); 1771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch convert_mode = ConvertReceiverMode::kNullOrUndefined; 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!callee->AsProperty()->IsSuperAccess()); 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 0); 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(callee->AsProperty()); 1779bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), 1780bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 1782109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(x10); 1783109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperands(x0, x10); 1784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch convert_mode = ConvertReceiverMode::kNotNullOrUndefined; 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitCall(expr, convert_mode); 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* key) { 1794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASM_LOCATION("FullCodeGenerator::EmitKeyedCallWithLoadIC"); 1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the key. 1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(key); 1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 0); 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), x0); 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(callee->AsProperty()); 1805bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), 1806bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 1809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(x10); 1810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperands(x0, x10); 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined); 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) { 1817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASM_LOCATION("FullCodeGenerator::EmitCall"); 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments. 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 1821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arg_count; i++) { 1822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(i)); 1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1825bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS); 18263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch SetCallPosition(expr, expr->tail_call_mode()); 1827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (expr->tail_call_mode() == TailCallMode::kAllow) { 1828109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_trace) { 1829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kTraceTailCall); 1830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Update profiling counters before the tail call since we will 1832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // not return to this function. 1833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterHandlingForReturnSequence(true); 1834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Code> code = 183662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeFactory::CallICTrampoline(isolate(), mode, expr->tail_call_mode()) 183762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch .code(); 183862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Mov(x3, IntFromSlot(expr->CallFeedbackICSlot())); 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, (arg_count + 1) * kXRegSize); 1840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Mov(x0, arg_count); 1841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallIC(code); 1842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordJSReturnSite(expr); 1845bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(1, x0); 1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ CallNew"); 1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // According to ECMA-262, section 11.2.2, page 44, the function 1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // expression in new calls must be evaluated before the 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // arguments. 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push constructor on the stack. If it's not a function it's used as 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ignored. 1858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!expr->expression()->IsSuperPropertyReference()); 1859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(expr->expression()); 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the arguments ("left-to-right") on the stack. 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the construct call builtin that handles allocation and 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // constructor invocation. 1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetConstructCallPosition(expr); 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load function and argument count into x1 and x0. 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, arg_count); 1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, arg_count * kXRegSize); 1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record call targets in unoptimized code. 187762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ EmitLoadFeedbackVector(x2); 1878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Mov(x3, SmiFromSlot(expr->CallNewFeedbackSlot())); 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallConstructStub stub(isolate()); 1881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallIC(stub.GetCode()); 1882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 1883bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER); 1884bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TestAndSplit(x0, kSmiTagMask, if_true, if_false, fall_through); 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) { 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE); 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(ge, if_true, if_false, fall_through); 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x0, x10, x11, JS_ARRAY_TYPE); 1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) { 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 1963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->PrepareTest(&materialize_true, &materialize_false, &if_true, 1964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &if_false, &fall_through); 1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(x0, x10, x11, JS_TYPED_ARRAY_TYPE); 1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) { 1976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(args->length() == 1); 1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(args->at(0)); 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->PrepareTest(&materialize_true, &materialize_false, &if_true, 1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &if_false, &fall_through); 1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(x0, if_false); 1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(x0, x10, x11, JS_PROXY_TYPE); 1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitClassOf"); 1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, null, function, non_function_constructor; 2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the object is not a JSReceiver, we return null. 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, &null); 2007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE); 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x10: object's map. 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x11: object's type. 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, &null); 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Return 'Function' for JSFunction objects. 20143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Cmp(x11, FIRST_FUNCTION_TYPE); 20153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); 20163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ B(hs, &function); 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the constructor in the map is a JS function. 2019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register instance_type = x14; 2020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ GetMapConstructor(x12, x10, x13, instance_type); 2021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Cmp(instance_type, JS_FUNCTION_TYPE); 2022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ B(ne, &non_function_constructor); 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x12 now contains the constructor function. Grab the 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instance class name from there. 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x13, FieldMemOperand(x12, JSFunction::kSharedFunctionInfoOffset)); 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(x13, SharedFunctionInfo::kInstanceClassNameOffset)); 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Functions have class 'Function'. 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&function); 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kFunction_stringRootIndex); 2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Objects with a non-function constructor have class 'Object'. 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&non_function_constructor); 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kObject_stringRootIndex); 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Non-JS objects have class null. 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&null); 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kNullValueRootIndex); 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All done. 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = x1; 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = x0; 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x3; 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(object); 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label need_conversion; 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label index_out_of_range; 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 206813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch StringCharCodeAtGenerator generator(object, index, result, &need_conversion, 206913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &need_conversion, &index_out_of_range); 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.GenerateFast(masm_); 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&index_out_of_range); 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // When the index is out of range, the spec requires us to return NaN. 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&need_conversion); 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the undefined value into the result register, which will 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // trigger conversion. 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NopRuntimeCallHelper call_helper; 2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper); 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result); 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(CallRuntime* expr) { 2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASM_LOCATION("FullCodeGenerator::EmitCall"); 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_LE(2, args->length()); 2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push target, receiver and arguments onto the stack. 2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (Expression* const arg : *args) { 2098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(arg); 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2100bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS); 2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Move target to x1. 2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int const argc = args->length() - 2; 2103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Peek(x1, (argc + 1) * kXRegSize); 2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the target. 2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(x0, argc); 2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 2107109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(argc + 1); 2108bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Discard the function left on TOS. 2110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->DropAndPlug(1, x0); 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) { 2114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(1, args->length()); 2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(args->at(0)); 2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(x0); 2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 2119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ldr(x0, FieldMemOperand(x0, Map::kPrototypeOffset)); 2120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(x0); 2121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference debug_is_active = 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::debug_is_active_address(isolate()); 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, debug_is_active); 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x0, MemOperand(x10)); 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(x0); 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { 2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(2, args->length()); 2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(0)); 2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(1)); 2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label runtime, done; 2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register result = x0; 2143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(JSIteratorResult::kSize, result, x10, x11, &runtime, 2144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register map_reg = x1; 2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register result_value = x2; 2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register boolean_done = x3; 2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register empty_fixed_array = x4; 2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register untagged_result = x5; 2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, map_reg); 2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(boolean_done); 2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(result_value); 2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(empty_fixed_array, Heap::kEmptyFixedArrayRootIndex); 2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize == 2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSObject::kElementsOffset); 2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSIteratorResult::kValueOffset + kPointerSize == 2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSIteratorResult::kDoneOffset); 2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ObjectUntag(untagged_result, result); 2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset)); 2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Stp(empty_fixed_array, empty_fixed_array, 2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand(untagged_result, JSObject::kPropertiesOffset)); 2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Stp(result_value, boolean_done, 2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand(untagged_result, JSIteratorResult::kValueOffset)); 2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); 2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ B(&done); 2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Bind(&runtime); 2168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kCreateIterResultObject); 2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Bind(&done); 2171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(x0); 2172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { 21763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Push function. 21773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadNativeContextSlot(expr->context_index(), x0); 21783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch PushOperand(x0); 21793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push undefined as the receiver. 2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); 2182109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); 2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetCallPosition(expr); 2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Peek(x1, (arg_count + 1) * kPointerSize); 2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(x0, arg_count); 2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), 2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 2196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (expr->op()) { 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::DELETE: { 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* property = expr->expression()->AsProperty(); 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property != NULL) { 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 2210109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(is_strict(language_mode()) 2211109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ? Runtime::kDeleteProperty_Strict 2212109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Runtime::kDeleteProperty_Sloppy); 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (proxy != NULL) { 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = proxy->var(); 2216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Delete of an unqualified identifier is disallowed in strict mode but 2217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // "delete this" is allowed. 2218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool is_this = var->is_this(); 2219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(is_sloppy(language_mode()) || is_this); 2220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (var->IsUnallocated()) { 2221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalObject(x12); 2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x11, Operand(var->name())); 2223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(x12, x11); 2224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kDeleteProperty_Sloppy); 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 222662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 222762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!var->IsLookupSlot()); 222862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result of deleting non-global, non-dynamic variables is false. 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The subexpression does not have side effects. 2231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(is_this); 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result of deleting non-property, non-variable reference is true. 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The subexpression may have side effects. 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(expr->expression()); 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(true); 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::VOID: { 2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(expr->expression()); 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(Heap::kUndefinedValueRootIndex); 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::NOT: { 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context()->IsEffect()) { 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unary NOT has no side effects so it's only necessary to visit the 2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // subexpression. Match the optimizing compiler by not branching. 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(expr->expression()); 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (context()->IsTest()) { 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const TestContext* test = TestContext::cast(context()); 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The labels are swapped for the recursive call. 2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForControl(expr->expression(), 2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test->false_label(), 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test->true_label(), 2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test->fall_through()); 2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(test->true_label(), test->false_label()); 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): This could be much more efficient using (for 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // example) the CSEL instruction. 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false, done; 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForControl(expr->expression(), 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &materialize_false, 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &materialize_true, 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &materialize_true); 2271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1); 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&materialize_true); 2274bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->MaterializeTrueId(), 2275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&materialize_false); 2280bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->MaterializeFalseId(), 2281bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context()->IsStackValue()) { 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::TYPEOF: { 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AccumulatorValueContext context(this); 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForTypeofValue(expr->expression()); 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Mov(x3, x0); 2299c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET); 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ CountOperation"); 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = expr->expression()->AsProperty(); 2315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(prop); 2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Evaluate expression and get value. 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (assign_type == VARIABLE) { 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccumulatorValueContext context(this); 2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(expr->expression()->AsVariableProxy()); 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reserve space for result of postfix operation. 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix() && !context()->IsEffect()) { 2325109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(xzr); 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (assign_type) { 2328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_PROPERTY: { 2329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put the object both on the stack and in the register. 2330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->obj()); 2331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Peek(LoadDescriptor::ReceiverRegister(), 0); 2332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitNamedPropertyLoad(prop); 2333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_PROPERTY: { 2337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->obj()); 2338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->key()); 2339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize); 2340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Peek(LoadDescriptor::NameRegister(), 0); 2341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitKeyedPropertyLoad(prop); 2342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 234562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 234662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 2347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case VARIABLE: 2348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need a second deoptimization point after loading the value 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in case evaluating the property load my have a side effect. 2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (assign_type == VARIABLE) { 2355bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER); 2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2357bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER); 2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline smi case if we are in a loop. 2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label stub_call, done; 2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count_value = expr->op() == Token::INC ? 1 : -1; 2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(expr->op())) { 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfNotSmi(x0, &slow); 2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save result for postfix expressions. 2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the result on the stack. If we have a named or keyed property we 2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // store the result under the receiver that is currently on top of the 2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack. 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, kPointerSize); 2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, kPointerSize * 2); 2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 238562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 2386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 238762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 2388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Adds(x0, x0, Smi::FromInt(count_value)); 2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(vc, &done); 2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call stub. Undo operation first. 2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Sub(x0, x0, Smi::FromInt(count_value)); 2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&stub_call); 2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow); 2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 24003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 24013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Convert old value into a number. 240213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 2403f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 2404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER); 2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save result for postfix expressions. 2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the result on the stack. If we have a named or keyed property 2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we store the result under the receiver that is currently on top 2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the stack. 2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 2414109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x0); 2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, kXRegSize); 2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, 2 * kXRegSize); 2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 242262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 2423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 242462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 2425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&stub_call); 2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, x0); 2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(count_value)); 2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(expr); 2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope scope(masm_); 2438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code(); 2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->CountBinOpFeedbackId()); 2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the value returned in x0. 2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 2446c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case VARIABLE: { 2447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { EffectContext context(this); 2450c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), 2451c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 2452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), 2453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context.Plug(x0); 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For all contexts except EffectConstant We have the result on 2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // top of the stack. 2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2462c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), 2463c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 2464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), 2465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2469c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: { 2471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 2472f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); 2473bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: { 2484109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::NameRegister()); 2485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 2486f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->CountSlot()); 2487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 249762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 249862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 249962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 250062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* sub_expr, 2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> check) { 2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof"); 2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ EmitLiteralCompareTypeof"); 2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { AccumulatorValueContext context(this); 2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForTypeofValue(sub_expr); 2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(check, factory->number_string())) { 2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof number_string"); 2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_true); 2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, Heap::kHeapNumberMapRootIndex); 2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->string_string())) { 2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof string_string"); 2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareObjectType(x0, x0, x1, FIRST_NONSTRING_TYPE); 2533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(lt, if_true, if_false, fall_through); 2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->symbol_string())) { 2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof symbol_string"); 2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x0, x0, x1, SYMBOL_TYPE); 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->boolean_string())) { 2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof boolean_string"); 2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(x0, Heap::kTrueValueRootIndex, if_true); 2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, Heap::kFalseValueRootIndex); 2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->undefined_string())) { 2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION( 2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "FullCodeGenerator::EmitLiteralCompareTypeof undefined_string"); 2547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfRoot(x0, Heap::kNullValueRootIndex, if_false); 2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for undetectable objects => true. 2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_false, if_true, 2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fall_through); 2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->function_string())) { 2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof function_string"); 2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 2558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); 2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ And(x1, x1, (1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)); 2560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareAndSplit(x1, Operand(1 << Map::kIsCallable), eq, if_true, 2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_false, fall_through); 2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->object_string())) { 2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof object_string"); 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(x0, Heap::kNullValueRootIndex, if_true); 2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 2567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfObjectType(x0, x10, x11, FIRST_JS_RECEIVER_TYPE, if_false, lt); 2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check for callable or undetectable objects => false. 2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ldrb(x10, FieldMemOperand(x10, Map::kBitFieldOffset)); 2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TestAndSplit(x10, (1 << Map::kIsCallable) | (1 << Map::kIsUndetectable), 2571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_true, if_false, fall_through); 2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof other"); 2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (if_false != fall_through) __ B(if_false); 2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ CompareOperation"); 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Try to generate an optimized comparison with a literal value. 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): This only checks common values like NaN or undefined. 2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Should it also handle ARM64 immediate operands? 2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (TryLiteralCompare(expr)) { 2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assign labels according to context()->PrepareTest. 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true; 2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_false; 2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op = expr->op(); 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->left()); 2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::IN: 2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->right()); 2604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 2605bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch EmitHasProperty(); 2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, Heap::kTrueValueRootIndex); 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::INSTANCEOF: { 2612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(expr->right()); 2613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 2614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(x1); 2615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET); 261662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RestoreContext(); 2617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 2618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(x0, Heap::kTrueValueRootIndex); 2619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(eq, if_true, if_false, fall_through); 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: { 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->right()); 2625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = CompareIC::ComputeCondition(op); 2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop the stack value. 2629109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(x1); 2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(op)) { 2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow_case; 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); 2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x1, x0); 2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(cond, if_true, if_false, NULL); 2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow_case); 2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareAndSplit(x0, 0, cond, if_true, if_false, fall_through); 2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert the result of the comparison into one expected for this 2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // expression's context. 2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* sub_expr, 2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NilValue nil) { 2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareNil"); 2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(sub_expr); 2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->op() == Token::EQ_STRICT) { 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex nil_value = nil == kNullValue ? 2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kNullValueRootIndex : 2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kUndefinedValueRootIndex; 2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, nil_value); 2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 26753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ JumpIfSmi(x0, if_false); 26763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 26773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); 26783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_false, if_true, 26793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch fall_through); 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) { 268762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Resumable functions are not supported. 268862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PushOperands(Register reg1, Register reg2) { 2692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(2); 2693109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(reg1, reg2); 2694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PushOperands(Register reg1, Register reg2, 2697109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register reg3) { 2698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(3); 2699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(reg1, reg2, reg3); 2700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PopOperands(Register reg1, Register reg2) { 2703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(2); 2704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(reg1, reg2); 2705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitOperandStackDepthCheck() { 2708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 2709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + 2710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch operand_stack_depth_ * kPointerSize; 2711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Sub(x0, fp, jssp); 2712109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Cmp(x0, Operand(expected_diff)); 2713109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(eq, kUnexpectedStackDepth); 2714109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2715109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) { 2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label allocate, done_allocate; 2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate and populate an object with this form: { value: VAL, done: DONE } 2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x0; 2723bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(JSIteratorResult::kSize, result, x10, x11, &allocate, 2724bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ B(&done_allocate); 2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Bind(&allocate); 2728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(Smi::FromInt(JSIteratorResult::kSize)); 2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace); 2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Bind(&done_allocate); 2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map_reg = x1; 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_value = x2; 2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register boolean_done = x3; 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register empty_fixed_array = x4; 2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register untagged_result = x5; 2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, map_reg); 27383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch PopOperand(result_value); 2739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(boolean_done, 2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); 2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(empty_fixed_array, Heap::kEmptyFixedArrayRootIndex); 2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize == 2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kElementsOffset); 2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSIteratorResult::kValueOffset + kPointerSize == 2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSIteratorResult::kDoneOffset); 2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ObjectUntag(untagged_result, result); 2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset)); 2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Stp(empty_fixed_array, empty_fixed_array, 2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(untagged_result, JSObject::kPropertiesOffset)); 2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Stp(result_value, boolean_done, 2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand(untagged_result, JSIteratorResult::kValueOffset)); 2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(all): I don't like this method. 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// It seems to me that in too many places x0 is used in place of this. 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Also, this function is not suitable for all places where x0 should be 2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// abstracted (eg. when used as an argument). But some places assume that the 2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// first argument register is x0, and use this function instead. 2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Considering that most of the register allocation is hard-coded in the 2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// FullCodeGen, that it is unlikely we will need to change it extensively, and 2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// that abstracting the allocation through functions would not yield any 2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// performance benefit, I think the existence of this function is debatable. 2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister FullCodeGenerator::result_register() { 2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return x0; 2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister FullCodeGenerator::context_register() { 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return cp; 2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 27743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) { 27753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(POINTER_SIZE_ALIGN(frame_offset) == frame_offset); 27763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Ldr(value, MemOperand(fp, frame_offset)); 27773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(POINTER_SIZE_ALIGN(frame_offset) == frame_offset); 2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(value, MemOperand(fp, frame_offset)); 2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(dst, ContextMemOperand(cp, context_index)); 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 2791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DeclarationScope* closure_scope = scope()->GetClosureScope(); 2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (closure_scope->is_script_scope() || 2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch closure_scope->is_module_scope()) { 2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Contexts nested in the native context have a canonical empty function 2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as their closure, not the anonymous closure containing the global 2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // code. 2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kSmiTag == 0); 2798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::CLOSURE_INDEX, x10); 2799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (closure_scope->is_eval_scope()) { 2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Contexts created by a call to eval have the same closure as the 2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context calling eval, not the anonymous closure containing the eval 2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code. Fetch it from the context. 2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, ContextMemOperand(cp, Context::CLOSURE_INDEX)); 2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(closure_scope->is_function_scope()); 2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(x10); 2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code, 2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc, 2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BackEdgeState target_state, 2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* replacement_code) { 2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Turn the jump into a nop. 2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address branch_address = pc - 3 * kInstructionSize; 2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate* isolate = unoptimized_code->GetIsolate(); 2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PatchingAssembler patcher(isolate, branch_address, 1); 2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Instruction::Cast(branch_address) 2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->IsNop(Assembler::INTERRUPT_CODE_NOP) || 2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Instruction::Cast(branch_address)->IsCondBranchImm() && 2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction::Cast(branch_address)->ImmPCOffset() == 2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6 * kInstructionSize)); 2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (target_state) { 2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INTERRUPT: 2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <decrement profiling counter> 2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. b.pl ok 2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. ldr x16, pc+<interrupt stub address> 2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. blr x16 2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ... more instructions. 2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok-label 2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump offset is 6 instructions. 2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.b(6, pl); 2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ON_STACK_REPLACEMENT: 2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <decrement profiling counter> 2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. mov x0, x0 (NOP) 2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. ldr x16, pc+<on-stack replacement address> 2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. blr x16 2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.nop(Assembler::INTERRUPT_CODE_NOP); 2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace the call address. 2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* load = Instruction::Cast(pc)->preceding(2); 2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address interrupt_address_pointer = 2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<Address>(load) + load->ImmPCOffset(); 2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((Memory::uint64_at(interrupt_address_pointer) == 2855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<uint64_t>( 2856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate->builtins()->OnStackReplacement()->entry())) || 2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Memory::uint64_at(interrupt_address_pointer) == 2858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<uint64_t>( 2859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate->builtins()->InterruptCheck()->entry())) || 2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Memory::uint64_at(interrupt_address_pointer) == 2861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<uint64_t>( 2862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate->builtins()->OnStackReplacement()->entry()))); 2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::uint64_at(interrupt_address_pointer) = 2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<uint64_t>(replacement_code->entry()); 2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code, reinterpret_cast<Address>(load), replacement_code); 2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate, 2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* unoptimized_code, 2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc) { 2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): There should be some extra assertions here (as in the ARM 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // back-end), but this function is gone in bleeding_edge so it might not 2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // matter anyway. 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* jump_or_nop = Instruction::Cast(pc)->preceding(3); 2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (jump_or_nop->IsNop(Assembler::INTERRUPT_CODE_NOP)) { 2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* load = Instruction::Cast(pc)->preceding(2); 2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t entry = Memory::uint64_at(reinterpret_cast<Address>(load) + 2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load->ImmPCOffset()); 2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry == reinterpret_cast<uint64_t>( 2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->OnStackReplacement()->entry())) { 2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ON_STACK_REPLACEMENT; 2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return INTERRUPT; 2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_ARM64 2900